Merge branch 'development' of https://github.com/aws-lumberyard-dev/o3de into scripting/rte_issues
This commit is contained in:
@@ -125,17 +125,6 @@
|
||||
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
|
||||
<Class name="AZStd::string" field="value1" value="@devroot@/*.waf_files" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
|
||||
<Class name="unsigned char" field="FilePatternType" value="1" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
|
||||
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
|
||||
<Class name="AZStd::string" field="element" value="ignore" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="AZStd::string" field="element" value="productdependency" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
|
||||
<Class name="AZStd::string" field="value1" value="*/editor/leveltemplates.xml" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
|
||||
@@ -207,27 +196,6 @@
|
||||
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
|
||||
<Class name="AZStd::string" field="value1" value="@devroot@/*wscript" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
|
||||
<Class name="unsigned char" field="FilePatternType" value="1" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
|
||||
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
|
||||
<Class name="AZStd::string" field="element" value="ignore" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="AZStd::string" field="element" value="productdependency" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
|
||||
<Class name="AZStd::string" field="value1" value=".*/assetprocessorplatformconfig.ini" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
|
||||
<Class name="unsigned char" field="FilePatternType" value="2" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
|
||||
<Class name="AZStd::set" field="FileTags" type="{166F208E-DE97-53FE-B349-BDD9FE9B8693}">
|
||||
<Class name="AZStd::string" field="element" value="editoronly" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::string" field="Comment" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="AZStd::pair" field="element" type="{941B5626-118F-55BC-925E-6E416A7520E4}">
|
||||
<Class name="AZStd::string" field="value1" value=".*/gems?/?.*/gem.json" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
<Class name="FileTagData" field="value2" version="2" type="{5F66E43B-548B-4AA8-8CD8-F6924F6031E6}">
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
"Version": 1,
|
||||
"ClassName": "GlobalBuildOptions",
|
||||
"ClassData": {
|
||||
"ShaderCompilerArguments" : {
|
||||
"DefaultMatrixOrder" : "Row",
|
||||
"AzslcAdditionalFreeArguments" : "--strip-unused-srgs"
|
||||
"ShaderCompilerArguments": {
|
||||
"DefaultMatrixOrder": "Row",
|
||||
"AzslcAdditionalFreeArguments": "--strip-unused-srgs"
|
||||
},
|
||||
"PreprocessorOptions": {
|
||||
"predefinedMacros": [ "AZSL=17" ],
|
||||
"projectIncludePaths": [
|
||||
"Gems/AtomTressFX/Assets/Shaders"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ set(ENABLED_GEMS
|
||||
|
||||
Camera
|
||||
EMotionFX
|
||||
AtomTressFX
|
||||
PhysX
|
||||
CameraFramework
|
||||
StartingPointMovement
|
||||
@@ -52,9 +53,6 @@ set(ENABLED_GEMS
|
||||
AWSCore
|
||||
AWSClientAuth
|
||||
AWSMetrics
|
||||
|
||||
|
||||
|
||||
|
||||
AudioSystem
|
||||
)
|
||||
|
||||
@@ -211,7 +211,7 @@ class Timeout:
|
||||
return time.time() > self.die_after
|
||||
|
||||
|
||||
screenshotsFolder = os.path.join(azlmbr.paths.devroot, "AtomTest", "Cache" "pc", "Screenshots")
|
||||
screenshotsFolder = os.path.join(azlmbr.paths.products, "Screenshots")
|
||||
|
||||
|
||||
class ScreenshotHelper:
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import azlmbr.legacy.general as general
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.render as render
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from editor_python_test_tools.utils import TestHelper
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from Atom.atom_utils.atom_constants import LIGHT_TYPES
|
||||
|
||||
@@ -16,7 +16,7 @@ import time
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import Atom.atom_utils.material_editor_utils as material_editor
|
||||
|
||||
@@ -27,10 +27,10 @@ TEST_MATERIAL_1 = "001_DefaultWhite.material"
|
||||
TEST_MATERIAL_2 = "002_BaseColorLerp.material"
|
||||
TEST_MATERIAL_3 = "003_MetalMatte.material"
|
||||
TEST_DATA_PATH = os.path.join(
|
||||
azlmbr.paths.devroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
|
||||
azlmbr.paths.engroot, "Gems", "Atom", "TestData", "TestData", "Materials", "StandardPbrTestCases"
|
||||
)
|
||||
MATERIAL_TYPE_PATH = os.path.join(
|
||||
azlmbr.paths.devroot, "Gems", "Atom", "Feature", "Common", "Assets",
|
||||
azlmbr.paths.engroot, "Gems", "Atom", "Feature", "Common", "Assets",
|
||||
"Materials", "Types", "StandardPBR.materialtype",
|
||||
)
|
||||
CACHE_FILE_EXTENSION = ".azmaterial"
|
||||
@@ -61,7 +61,7 @@ def run():
|
||||
print(f"Material opened: {material_editor.is_open(document_id)}")
|
||||
|
||||
# Verify if the test material exists initially
|
||||
target_path = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL)
|
||||
target_path = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL)
|
||||
print(f"Test asset doesn't exist initially: {not os.path.exists(target_path)}")
|
||||
|
||||
# 2) Test Case: Creating a New Material Using Existing One
|
||||
@@ -109,10 +109,10 @@ def run():
|
||||
# Assign new color to the material file and save the document as copy
|
||||
expected_color_1 = math.Color(0.5, 0.5, 0.5, 1.0)
|
||||
material_editor.set_property(document_id, property_name, expected_color_1)
|
||||
target_path_1 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_1)
|
||||
target_path_1 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_1)
|
||||
cache_file_name_1 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_1', '.material')
|
||||
cache_file_1 = f"{cache_file_name_1[0]}{CACHE_FILE_EXTENSION}"
|
||||
target_path_1_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_1)
|
||||
target_path_1_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_1)
|
||||
material_editor.save_document_as_copy(document_id, target_path_1)
|
||||
material_editor.wait_for_condition(lambda: os.path.exists(target_path_1_cache), 4.0)
|
||||
|
||||
@@ -120,10 +120,10 @@ def run():
|
||||
# Assign new color to the material file save the document as child
|
||||
expected_color_2 = math.Color(0.75, 0.75, 0.75, 1.0)
|
||||
material_editor.set_property(document_id, property_name, expected_color_2)
|
||||
target_path_2 = os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Materials", NEW_MATERIAL_2)
|
||||
target_path_2 = os.path.join(azlmbr.paths.projectroot, "Materials", NEW_MATERIAL_2)
|
||||
cache_file_name_2 = os.path.splitext(NEW_MATERIAL_1) # Example output: ('test_material_2', '.material')
|
||||
cache_file_2 = f"{cache_file_name_2[0]}{CACHE_FILE_EXTENSION}"
|
||||
target_path_2_cache = os.path.join(azlmbr.paths.devassets, "Cache", "pc", "materials", cache_file_2)
|
||||
target_path_2_cache = os.path.join(azlmbr.paths.products, "materials", cache_file_2)
|
||||
material_editor.save_document_as_child(document_id, target_path_2)
|
||||
material_editor.wait_for_condition(lambda: os.path.exists(target_path_2_cache), 4.0)
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import sys
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||
|
||||
@@ -17,7 +17,7 @@ import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from editor_python_test_tools.editor_test_helper import EditorTestHelper
|
||||
|
||||
@@ -14,7 +14,7 @@ import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, "Gem", "PythonTests"))
|
||||
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
from Atom.atom_utils import atom_component_helper, atom_constants, screenshot_utils
|
||||
|
||||
@@ -42,7 +42,6 @@ class TestEditorAutomation(object):
|
||||
"editor command line arg bar",
|
||||
"editor command line arg baz",
|
||||
"editor engroot set",
|
||||
"editor devroot set",
|
||||
"path resolved worked"
|
||||
]
|
||||
|
||||
|
||||
@@ -20,12 +20,6 @@ if (engroot is not None and len(engroot) is not 0):
|
||||
print ('engroot is {}'.format(engroot))
|
||||
print ('editor engroot set')
|
||||
|
||||
# make sure the @devroot@ exists as a azlmbr.paths property
|
||||
devroot = azlmbr.paths.devroot
|
||||
if (devroot is not None and len(devroot) != 0):
|
||||
print ('devroot is {}'.format(devroot))
|
||||
print ('editor devroot set')
|
||||
|
||||
# resolving a basic path
|
||||
path = azlmbr.paths.resolve_path('@engroot@/engineassets/texturemsg/defaultsolids.mtl')
|
||||
if (len(path) != 0 and path.find('@engroot@') == -1):
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import azlmbr.entity as entity
|
||||
import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
|
||||
from automatedtesting_shared.editor_test_helper import EditorTestHelper
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
|
||||
pyRunFile @devroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done
|
||||
pyRunFile @engroot@/Tests/hydra/LevelComponentCommands_test_case.py exit_when_done
|
||||
@@ -1,2 +1,2 @@
|
||||
# this file is copied to $/dev/editor_autoexec.cfg so the the Editor automation runs for this Hydra test
|
||||
pyRunFile @devroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py
|
||||
pyRunFile @engroot@/Tests/hydra/ViewportTitleDlgCommands_test_case.py
|
||||
@@ -96,19 +96,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_
|
||||
|
||||
## GradientSignal ##
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::GradientSignalTests_Periodic
|
||||
TEST_SERIAL
|
||||
TEST_SUITE periodic
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/gradient_signal/TestSuite_Periodic.py
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
Legacy::Editor
|
||||
AutomatedTesting.Assets
|
||||
COMPONENT
|
||||
LargeWorlds
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::GradientSignalTests_Periodic_Optimized
|
||||
TEST_SERIAL
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ def DynamicSliceInstanceSpawner_Embedded_E2E():
|
||||
# 6) Save and export to engine
|
||||
general.save_level()
|
||||
general.export_to_engine()
|
||||
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
|
||||
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
|
||||
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ def DynamicSliceInstanceSpawner_External_E2E():
|
||||
# 6) Save and export to engine
|
||||
general.save_level()
|
||||
general.export_to_engine()
|
||||
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
|
||||
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
|
||||
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ def LayerBlender_E2E_Editor():
|
||||
# 6) Save and export to engine
|
||||
general.save_level()
|
||||
general.export_to_engine()
|
||||
pak_path = os.path.join(paths.devroot, "AutomatedTesting", "cache", "pc", "levels", lvl_name, "level.pak")
|
||||
pak_path = os.path.join(paths.products, "levels", lvl_name, "level.pak")
|
||||
Report.result(Tests.saved_and_exported, os.path.exists(pak_path))
|
||||
|
||||
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ import pytest
|
||||
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ import azlmbr.vegetation as vegetation
|
||||
import azlmbr.areasystem as areasystem
|
||||
import azlmbr.paths
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests'))
|
||||
sys.path.append(os.path.join(azlmbr.paths.projectroot, 'Gem', 'PythonTests'))
|
||||
import editor_python_test_tools.hydra_editor_utils as hydra
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z
|
||||
# Create a "flat surface" entity to use as a plantable vegetation surface
|
||||
surface_entity = hydra.Entity(name)
|
||||
surface_entity.create_entity(
|
||||
center_point,
|
||||
center_point,
|
||||
["Box Shape", "Shape Surface Tag Emitter"]
|
||||
)
|
||||
if surface_entity.id.IsValid():
|
||||
@@ -56,7 +56,7 @@ def create_vegetation_area(name, center_point, box_size_x, box_size_y, box_size_
|
||||
# Create a vegetation area entity to use as our test vegetation spawner
|
||||
spawner_entity = hydra.Entity(name)
|
||||
spawner_entity.create_entity(
|
||||
center_point,
|
||||
center_point,
|
||||
["Vegetation Layer Spawner", "Box Shape", "Vegetation Asset List"]
|
||||
)
|
||||
if spawner_entity.id.IsValid():
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[General]
|
||||
version=1
|
||||
startScript="ImportActor -filename \"@assets@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"
|
||||
startScript="ImportActor -filename \"@products@/characters/cowboy/actor/cowboy_01.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\n"
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[General]
|
||||
version=1
|
||||
startScript="ImportActor -filename \"@assets@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@assets@/Levels/Physics/C15096734_PhysxMaterials_DefaultMaterialLibrary/rin_physics.animgraph\"\n"
|
||||
startScript="ImportActor -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_skeleton_newgeo.actor\"\nCreateActorInstance -actorID %LASTRESULT% -xPos 0.000000 -yPos 0.000000 -zPos 0.000000 -xScale 1.000000 -yScale 1.000000 -zScale 1.000000 -rot 0.00000000,0.00000000,0.00000000,1.00000000\nLoadMotionSet -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/custom_motionset.motionset\"\nLoadAnimGraph -filename \"@products@/levels/physics/c15096734_physxmaterials_defaultmateriallibrary/rin_physics.animgraph\"\n"
|
||||
|
||||
@@ -51,6 +51,14 @@
|
||||
[
|
||||
"Gems/UiBasics"
|
||||
]
|
||||
},
|
||||
"Hair":
|
||||
{
|
||||
"SourcePaths":
|
||||
[
|
||||
"Gems/AtomTressFX/Assets",
|
||||
"Gems/AtomTressFX/Assets/Passes"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Legacy::CryCommon
|
||||
3rdParty::zlib
|
||||
PUBLIC
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Gui
|
||||
@@ -105,7 +104,6 @@ ly_add_target(
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::tiff
|
||||
3rdParty::squish-ccr
|
||||
3rdParty::zlib
|
||||
3rdParty::AWSNativeSDK::STS
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorCommon
|
||||
|
||||
@@ -278,17 +278,16 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder)
|
||||
|
||||
void CFolderTreeCtrl::AddItem(const QString& path)
|
||||
{
|
||||
QString folder;
|
||||
QString fileNameWithoutExtension;
|
||||
QString ext;
|
||||
|
||||
Path::Split(path, folder, fileNameWithoutExtension, ext);
|
||||
AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) };
|
||||
AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Extension();
|
||||
folder = folder.ParentPath();
|
||||
|
||||
auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
if (regex.exactMatch(path))
|
||||
{
|
||||
CTreeItem* folderTreeItem = CreateFolderItems(folder);
|
||||
folderTreeItem->AddChild(fileNameWithoutExtension, path, eTreeImage_File);
|
||||
CTreeItem* folderTreeItem = CreateFolderItems(QString::fromUtf8(folder.c_str(), static_cast<int>(folder.Native().size())));
|
||||
folderTreeItem->AddChild(QString::fromUtf8(fileNameWithoutExtension.c_str(),
|
||||
static_cast<int>(fileNameWithoutExtension.Native().size())), path, eTreeImage_File);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ public:
|
||||
protected:
|
||||
void SetupEnvironment() override
|
||||
{
|
||||
AttachEditorCoreAZEnvironment(AZ::Environment::GetInstance());
|
||||
m_allocatorScope.ActivateAllocators();
|
||||
m_cryPak = new NiceMock<CryPakMock>();
|
||||
|
||||
@@ -49,6 +50,7 @@ protected:
|
||||
{
|
||||
delete m_cryPak;
|
||||
m_allocatorScope.DeactivateAllocators();
|
||||
DetachEditorCoreAZEnvironment();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,22 +5,29 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include "EditorDefs.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include "Util/PathUtil.h"
|
||||
#include <CrySystemBus.h>
|
||||
|
||||
TEST(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <Util/PathUtil.h>
|
||||
namespace UnitTest
|
||||
{
|
||||
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
|
||||
QString pngExtension(".png");
|
||||
class PathUtil
|
||||
: public ScopedAllocatorSetupFixture
|
||||
{
|
||||
};
|
||||
|
||||
// Create a string of lenth AZ_MAX_PATH_LEN that ends in .png
|
||||
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
|
||||
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPath);
|
||||
TEST_F(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
|
||||
{
|
||||
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
|
||||
QString pngExtension(".png");
|
||||
|
||||
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
|
||||
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPathPlusOne);
|
||||
// Create a string of length AZ_MAX_PATH_LEN that ends in .png
|
||||
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
|
||||
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
Path::GamePathToFullPath(longStringMaxPath);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
|
||||
|
||||
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
|
||||
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPathPlusOne);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2642,7 +2642,7 @@ void CCryEditApp::OnFileResaveSlices()
|
||||
sliceAssetInfos.reserve(5000);
|
||||
AZ::Data::AssetCatalogRequests::AssetEnumerationCB sliceCountCb = [&sliceAssetInfos]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @devroot@)
|
||||
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @engroot@)
|
||||
if (info.m_assetType == azrtti_typeid<AZ::SliceAsset>() && info.m_relativePath[0] != '@')
|
||||
{
|
||||
sliceAssetInfos.push_back(info);
|
||||
|
||||
@@ -1108,7 +1108,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
if (QFileInfo(filename).isRelative())
|
||||
{
|
||||
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
|
||||
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@devassets@"))).absoluteFilePath(fullPathName));
|
||||
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@projectroot@"))).absoluteFilePath(fullPathName));
|
||||
}
|
||||
|
||||
if (!CFileUtil::OverwriteFile(fullPathName))
|
||||
@@ -2159,7 +2159,7 @@ bool CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString&
|
||||
xmlAr.bLoading = true;
|
||||
|
||||
// bound to the level folder, as if it were the assets folder.
|
||||
// this mounts (whateverlevelname.ly) as @assets@/Levels/whateverlevelname/ and thus it works...
|
||||
// this mounts (whateverlevelname.ly) as @products@/Levels/whateverlevelname/ and thus it works...
|
||||
bool openLevelPakFileSuccess = pIPak->OpenPack(levelPath.toUtf8().data(), absoluteLevelPath.toUtf8().data());
|
||||
if (!openLevelPakFileSuccess)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent)
|
||||
{
|
||||
AZ::IO::Path newSourcePath = jsonSourcePathPointer;
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
// Editor
|
||||
#include "CryEdit.h"
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEditorFileMonitor::CEditorFileMonitor()
|
||||
{
|
||||
@@ -177,26 +179,14 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
|
||||
// Make file relative to PrimaryCD folder.
|
||||
QString filename = rChange.filename;
|
||||
|
||||
// Remove game directory if present in path.
|
||||
const QString rootPath =
|
||||
QDir::fromNativeSeparators(QString::fromLatin1(Path::GetEditingRootFolder().c_str()));
|
||||
if (filename.startsWith(rootPath, Qt::CaseInsensitive))
|
||||
{
|
||||
filename = filename.right(filename.length() - rootPath.length());
|
||||
}
|
||||
// Make path relative to the the project directory
|
||||
AZ::IO::Path projectPath{ AZ::Utils::GetProjectPath() };
|
||||
AZ::IO::FixedMaxPath projectRelativeFilePath = AZ::IO::PathView(filename.toUtf8().constData()).LexicallyProximate(
|
||||
projectPath);
|
||||
|
||||
// Make sure there is no leading slash
|
||||
if (!filename.isEmpty() && (filename[0] == '\\' || filename[0] == '/'))
|
||||
if (!projectRelativeFilePath.empty())
|
||||
{
|
||||
filename = filename.mid(1);
|
||||
}
|
||||
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
//remove game name. Make it relative to the game folder
|
||||
const QString filenameRelGame = RemoveGameName(filename);
|
||||
const int extIndex = filename.lastIndexOf('.');
|
||||
const QString ext = filename.right(filename.length() - 1 - extIndex);
|
||||
AZ::IO::PathView ext = projectRelativeFilePath.Extension();
|
||||
|
||||
// Check for File Monitor callback
|
||||
std::vector<SFileChangeCallback>::iterator iter;
|
||||
@@ -207,15 +197,11 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
|
||||
// We compare against length of callback string, so we get directory matches as well as full filenames
|
||||
if (sCallback.pListener)
|
||||
{
|
||||
if (sCallback.extension == "*" || ext.compare(sCallback.extension, Qt::CaseInsensitive) == 0)
|
||||
if (sCallback.extension == "*" || AZ::IO::PathView(sCallback.extension.toUtf8().constData()) == ext)
|
||||
{
|
||||
if (filenameRelGame.compare(sCallback.item, Qt::CaseInsensitive) == 0)
|
||||
if (AZ::IO::PathView(sCallback.item.toUtf8().constData()) == projectRelativeFilePath)
|
||||
{
|
||||
sCallback.pListener->OnFileChange(qPrintable(filenameRelGame), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
}
|
||||
else if (filename.compare(sCallback.item, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
sCallback.pListener->OnFileChange(qPrintable(filename), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
sCallback.pListener->OnFileChange(qPrintable(projectRelativeFilePath.c_str()), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,7 @@ void GetSelectedEntitiesSetWithFlattenedHierarchy(AzToolsFramework::EntityIdSet&
|
||||
}
|
||||
|
||||
SandboxIntegrationManager::SandboxIntegrationManager()
|
||||
: m_inObjectPickMode(false)
|
||||
, m_startedUndoRecordingNestingLevel(0)
|
||||
: m_startedUndoRecordingNestingLevel(0)
|
||||
, m_dc(nullptr)
|
||||
, m_notificationWindowManager(new AzToolsFramework::SliceOverridesNotificationWindowManager())
|
||||
{
|
||||
@@ -1000,62 +999,6 @@ void SandboxIntegrationManager::SetupSliceContextMenu_Modify(QMenu* menu, const
|
||||
revertAction->setEnabled(canRevert);
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::HandleObjectModeSelection(const AZ::Vector2& point, [[maybe_unused]] int flags, bool& handled)
|
||||
{
|
||||
// Todo - Use a custom "edit tool". This will eliminate the need for this bus message entirely, which technically
|
||||
// makes this feature less intrusive on Sandbox.
|
||||
// UPDATE: This is now provided by EditorPickEntitySelection when the new Viewport Interaction Model changes are enabled.
|
||||
if (m_inObjectPickMode)
|
||||
{
|
||||
CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport();
|
||||
const QPoint viewPoint(static_cast<int>(point.GetX()), static_cast<int>(point.GetY()));
|
||||
|
||||
HitContext hitInfo;
|
||||
hitInfo.view = view;
|
||||
if (view->HitTest(viewPoint, hitInfo))
|
||||
{
|
||||
if (hitInfo.object && (hitInfo.object->GetType() == OBJTYPE_AZENTITY))
|
||||
{
|
||||
CComponentEntityObject* entityObject = static_cast<CComponentEntityObject*>(hitInfo.object);
|
||||
AzToolsFramework::EditorPickModeRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPickModeRequests::PickModeSelectEntity, entityObject->GetAssociatedEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorPickModeRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPickModeRequests::StopEntityPickMode);
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr)
|
||||
{
|
||||
if (m_inObjectPickMode)
|
||||
{
|
||||
cursorId = static_cast<AZ::u64>(STD_CURSOR_HAND);
|
||||
cursorStr = "Pick an entity...";
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::OnEntityPickModeStarted()
|
||||
{
|
||||
m_inObjectPickMode = true;
|
||||
|
||||
// Currently this object pick mode is activated only via PropertyEntityIdCtrl picker.
|
||||
// When the picker button is clicked, we transfer focus to the viewport so the
|
||||
// spacebar can still be used to activate selection helpers.
|
||||
if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport())
|
||||
{
|
||||
view->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::OnEntityPickModeStopped()
|
||||
{
|
||||
m_inObjectPickMode = false;
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::CreateEditorRepresentation(AZ::Entity* entity)
|
||||
{
|
||||
IEditor* editor = GetIEditor();
|
||||
@@ -1952,7 +1895,7 @@ void SandboxIntegrationManager::MakeSliceFromEntities(const AzToolsFramework::En
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(entitiesAndDescendants,
|
||||
&AzToolsFramework::ToolsApplicationRequestBus::Events::GatherEntitiesAndAllDescendents, entities);
|
||||
|
||||
const AZStd::string slicesAssetsPath = "@devassets@/Slices";
|
||||
const AZStd::string slicesAssetsPath = "@projectroot@/Slices";
|
||||
|
||||
if (!gEnv->pFileIO->Exists(slicesAssetsPath.c_str()))
|
||||
{
|
||||
|
||||
@@ -93,7 +93,6 @@ namespace AzToolsFramework
|
||||
class SandboxIntegrationManager
|
||||
: private AzToolsFramework::ToolsApplicationEvents::Bus::Handler
|
||||
, private AzToolsFramework::EditorRequests::Bus::Handler
|
||||
, private AzToolsFramework::EditorPickModeNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorContextMenuBus::Handler
|
||||
, private AzToolsFramework::EditorWindowRequests::Bus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
@@ -140,8 +139,6 @@ private:
|
||||
QDockWidget* InstanceViewPane(const char* paneName) override;
|
||||
void CloseViewPane(const char* paneName) override;
|
||||
void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override;
|
||||
void HandleObjectModeSelection(const AZ::Vector2& point, int flags, bool& handled) override;
|
||||
void UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr) override;
|
||||
void CreateEditorRepresentation(AZ::Entity* entity) override;
|
||||
bool DestroyEditorRepresentation(AZ::EntityId entityId, bool deleteAZEntity) override;
|
||||
void CloneSelection(bool& handled) override;
|
||||
@@ -175,10 +172,6 @@ private:
|
||||
QWidget* GetAppMainWindow() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// EditorPickModeNotificationBus
|
||||
void OnEntityPickModeStarted() override;
|
||||
void OnEntityPickModeStopped() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzToolsFramework::EditorContextMenu::Bus::Handler overrides
|
||||
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
|
||||
@@ -281,7 +274,6 @@ private:
|
||||
private:
|
||||
AZ::Vector2 m_contextMenuViewPoint;
|
||||
|
||||
int m_inObjectPickMode;
|
||||
short m_startedUndoRecordingNestingLevel; // used in OnBegin/EndUndo to ensure we only accept undo's we started recording
|
||||
|
||||
AzToolsFramework::SliceOverridesNotificationWindowManager* m_notificationWindowManager;
|
||||
|
||||
@@ -30,6 +30,7 @@ class CXTPDockingPaneLayout; // Needed for settings.h
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <Util/PathUtil.h>
|
||||
@@ -47,41 +48,6 @@ class CXTPDockingPaneLayout; // Needed for settings.h
|
||||
const char* AssetImporterWindow::s_documentationWebAddress = "http://docs.aws.amazon.com/lumberyard/latest/userguide/char-fbx-importer.html";
|
||||
const AZ::Uuid AssetImporterWindow::s_browseTag = AZ::Uuid::CreateString("{C240D2E1-BFD2-4FFA-BB5B-CC0FA389A5D3}");
|
||||
|
||||
void MakeUserFriendlySourceAssetPath(QString& out, const QString& sourcePath)
|
||||
{
|
||||
char devAssetsRoot[AZ_MAX_PATH_LEN] = { 0 };
|
||||
if (!gEnv->pFileIO->ResolvePath("@devroot@", devAssetsRoot, AZ_MAX_PATH_LEN))
|
||||
{
|
||||
out = sourcePath;
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::replace(devAssetsRoot, devAssetsRoot + AZ_MAX_PATH_LEN- 1, AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
|
||||
// Find if the sourcePathArray is a sub directory of the devAssets folder
|
||||
// Keep reference to sourcePathArray long enough to use in PathView
|
||||
QByteArray sourcePathArray = sourcePath.toUtf8();
|
||||
AZ::IO::PathView sourcePathRootView(sourcePathArray.data());
|
||||
AZ::IO::PathView devAssetsRootView(devAssetsRoot);
|
||||
auto [sourcePathIter, devAssetsIter] = AZStd::mismatch(sourcePathRootView.begin(), sourcePathRootView.end(),
|
||||
devAssetsRootView.begin(), devAssetsRootView.end());
|
||||
// If the devAssets path iterator is not equal to the end, then there was a mismistch while comparing it
|
||||
// against the source path indicating that the source path is not a sub-directory
|
||||
if (devAssetsIter != devAssetsRootView.end())
|
||||
{
|
||||
out = sourcePath;
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = aznumeric_cast<int>(strlen(devAssetsRoot));
|
||||
if (sourcePath.at(offset) == AZ_CORRECT_FILESYSTEM_SEPARATOR)
|
||||
{
|
||||
++offset;
|
||||
}
|
||||
out = sourcePath.right(sourcePath.length() - offset);
|
||||
|
||||
}
|
||||
|
||||
AssetImporterWindow::AssetImporterWindow()
|
||||
: AssetImporterWindow(nullptr)
|
||||
{
|
||||
@@ -102,7 +68,7 @@ AssetImporterWindow::AssetImporterWindow(QWidget* parent)
|
||||
|
||||
AssetImporterWindow::~AssetImporterWindow()
|
||||
{
|
||||
AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
"Processing overlay (and potentially background thread) still active at destruction.");
|
||||
AZ_Assert(!m_processingOverlay, "Processing overlay (and potentially background thread) still active at destruction.");
|
||||
}
|
||||
@@ -133,7 +99,7 @@ void AssetImporterWindow::OpenFile(const AZStd::string& filePath)
|
||||
QMessageBox::warning(this, "In progress", "Unable to close one or more windows at this time.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OpenFileInternal(filePath);
|
||||
}
|
||||
|
||||
@@ -146,7 +112,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
|
||||
if (m_processingOverlay)
|
||||
{
|
||||
AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
"Processing overlay present, but not the index in the overlay for it.");
|
||||
if (m_processingOverlay->HasProcessingCompleted())
|
||||
{
|
||||
@@ -157,7 +123,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
|
||||
QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
ev->ignore();
|
||||
return;
|
||||
@@ -165,7 +131,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
|
||||
QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
ev->ignore();
|
||||
return;
|
||||
@@ -199,7 +165,9 @@ void AssetImporterWindow::Init()
|
||||
// Load the style sheets
|
||||
AzQtComponents::StylesheetPreprocessor styleSheetProcessor(nullptr);
|
||||
|
||||
AZStd::string mainWindowQSSPath = Path::GetEditingRootFolder() + "\\Editor\\Styles\\AssetImporterWindow.qss";
|
||||
auto mainWindowQSSPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
|
||||
mainWindowQSSPath /= "Editor/Styles/AssetImporterWindow.qss";
|
||||
mainWindowQSSPath.MakePreferred();
|
||||
QFile mainWindowStyleSheetFile(mainWindowQSSPath.c_str());
|
||||
if (mainWindowStyleSheetFile.open(QFile::ReadOnly))
|
||||
{
|
||||
@@ -212,7 +180,7 @@ void AssetImporterWindow::Init()
|
||||
{
|
||||
ui->m_actionInspect->setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
ResetMenuAccess(WindowState::InitialNothingLoaded);
|
||||
|
||||
// Setup the overlay system, and set the root to be the root display. The root display has the browse,
|
||||
@@ -220,7 +188,7 @@ void AssetImporterWindow::Init()
|
||||
m_overlay.reset(aznew AZ::SceneAPI::UI::OverlayWidget(this));
|
||||
m_rootDisplay.reset(aznew ImporterRootDisplay(m_serializeContext));
|
||||
connect(m_rootDisplay.data(), &ImporterRootDisplay::UpdateClicked, this, &AssetImporterWindow::UpdateClicked);
|
||||
|
||||
|
||||
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerAdded, this, &AssetImporterWindow::OverlayLayerAdded);
|
||||
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerRemoved, this, &AssetImporterWindow::OverlayLayerRemoved);
|
||||
|
||||
@@ -242,7 +210,7 @@ void AssetImporterWindow::Init()
|
||||
AZStd::string joinedExtensions;
|
||||
AzFramework::StringFunc::Join(joinedExtensions, extensions.begin(), extensions.end(), " or ");
|
||||
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string::format(
|
||||
"%s files are available for use after placing them in any folder within your game project. "
|
||||
"These files will automatically be processed and may be accessed via the Asset Browser. <a href=\"%s\">Learn more...</a>",
|
||||
@@ -250,13 +218,13 @@ void AssetImporterWindow::Init()
|
||||
|
||||
ui->m_initialPromptFirstLine->setText(firstLineText.c_str());
|
||||
|
||||
AZStd::string secondLineText =
|
||||
AZStd::string secondLineText =
|
||||
AZStd::string::format("To adjust the %s settings, right-click the file in the Asset Browser and select \"Edit Settings\" from the context menu.", joinedExtensions.c_str());
|
||||
ui->m_initialPromptSecondLine->setText(secondLineText.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string::format(
|
||||
"Files are available for use after placing them in any folder within your game project. "
|
||||
"These files will automatically be processed and may be accessed via the Asset Browser. <a href=\"%s\">Learn more...</a>", s_documentationWebAddress);
|
||||
@@ -282,12 +250,12 @@ void AssetImporterWindow::OpenFileInternal(const AZStd::string& filePath)
|
||||
auto asyncLoadHandler = AZStd::make_shared<AZ::SceneAPI::SceneUI::AsyncOperationProcessingHandler>(
|
||||
s_browseTag,
|
||||
[this, filePath]()
|
||||
{
|
||||
m_assetImporterDocument->LoadScene(filePath);
|
||||
{
|
||||
m_assetImporterDocument->LoadScene(filePath);
|
||||
},
|
||||
[this]()
|
||||
{
|
||||
HandleAssetLoadingCompleted();
|
||||
HandleAssetLoadingCompleted();
|
||||
}, this);
|
||||
|
||||
m_processingOverlay.reset(new ProcessingOverlayWidget(m_overlay.data(), ProcessingOverlayWidget::Layout::Loading, s_browseTag));
|
||||
@@ -304,7 +272,7 @@ bool AssetImporterWindow::IsAllowedToChangeSourceFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
|
||||
QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
|
||||
"You have unsaved changes. Do you want to discard those changes?",
|
||||
QMessageBox::StandardButton::Discard | QMessageBox::StandardButton::Cancel, this);
|
||||
messageBox.exec();
|
||||
@@ -406,7 +374,7 @@ void AssetImporterWindow::OnSceneResetRequested()
|
||||
else
|
||||
{
|
||||
m_assetImporterDocument->ClearScene();
|
||||
AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
|
||||
AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
|
||||
result.GetResult() == ProcessingResult::Failure ? "Failure" : "Ignored");
|
||||
}
|
||||
},
|
||||
@@ -456,7 +424,7 @@ void AssetImporterWindow::OnInspect()
|
||||
// make sure the inspector doesn't outlive the AssetImporterWindow, since we own the data it will be inspecting.
|
||||
auto* theInspectWidget = aznew AZ::SceneAPI::UI::SceneGraphInspectWidget(*m_assetImporterDocument->GetScene());
|
||||
QObject::connect(this, &QObject::destroyed, theInspectWidget, [theInspectWidget]() { theInspectWidget->window()->close(); } );
|
||||
|
||||
|
||||
m_overlay->PushLayer(label, theInspectWidget, "Scene Inspector", buttons);
|
||||
}
|
||||
|
||||
@@ -483,7 +451,7 @@ void AssetImporterWindow::OverlayLayerRemoved()
|
||||
else
|
||||
{
|
||||
ResetMenuAccess(WindowState::InitialNothingLoaded);
|
||||
|
||||
|
||||
ui->m_initialBrowseContainer->show();
|
||||
m_rootDisplay->hide();
|
||||
}
|
||||
@@ -533,8 +501,9 @@ void AssetImporterWindow::HandleAssetLoadingCompleted()
|
||||
m_fullSourcePath = m_assetImporterDocument->GetScene()->GetSourceFilename();
|
||||
SetTitle(m_fullSourcePath.c_str());
|
||||
|
||||
QString userFriendlyFileName;
|
||||
MakeUserFriendlySourceAssetPath(userFriendlyFileName, m_fullSourcePath.c_str());
|
||||
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
|
||||
AZ::IO::FixedMaxPath relativeSourcePath = AZ::IO::PathView(m_fullSourcePath).LexicallyProximate(projectPath);
|
||||
auto userFriendlyFileName = QString::fromUtf8(relativeSourcePath.c_str(), static_cast<int>(relativeSourcePath.Native().size()));
|
||||
m_rootDisplay->SetSceneDisplay(userFriendlyFileName, m_assetImporterDocument->GetScene());
|
||||
|
||||
// Once we've browsed to something successfully, we need to hide the initial browse button layer and
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
@@ -50,22 +52,15 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZStd::string cleanPath = filePath;
|
||||
if (AzFramework::StringFunc::Path::IsRelative(filePath.c_str()))
|
||||
AZ::IO::Path enginePath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
const char* absolutePath = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(absolutePath,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetAbsoluteDevRootFolderPath);
|
||||
AZ_Assert(absolutePath, "Unable to retrieve the dev folder path");
|
||||
AzFramework::StringFunc::Path::Join(absolutePath, cleanPath.c_str(), cleanPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normalizing is not needed if the path is relative as Join(...) will also normalize.
|
||||
AzFramework::StringFunc::Path::Normalize(cleanPath);
|
||||
settingsRegistry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
|
||||
auto sceneIt = m_scenes.find(cleanPath);
|
||||
AZ::IO::Path cleanPath = (enginePath / filePath).LexicallyNormal();
|
||||
|
||||
auto sceneIt = m_scenes.find(cleanPath.Native());
|
||||
if (sceneIt != m_scenes.end())
|
||||
{
|
||||
AZStd::shared_ptr<SceneAPI::Containers::Scene> scene = sceneIt->second.lock();
|
||||
@@ -98,14 +93,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneAPI::Containers::Scene> scene =
|
||||
AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
|
||||
AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath.Native(), sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
|
||||
if (!scene)
|
||||
{
|
||||
AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_scenes.emplace(AZStd::move(cleanPath), scene);
|
||||
m_scenes.emplace(AZStd::move(cleanPath.Native()), scene);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ ly_add_target(
|
||||
EDITOR_COMMON_IMPORTS
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::zlib
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
Legacy::CryCommon
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace ProjectSettingsTool
|
||||
, LastPathBus::Handler()
|
||||
, m_ui(new Ui::ProjectSettingsToolWidget())
|
||||
, m_reconfigureProcess()
|
||||
, m_devRoot(GetDevRoot())
|
||||
, m_projectRoot(GetProjectRoot())
|
||||
, m_projectName(GetProjectName())
|
||||
, m_plistsInitVector(
|
||||
|
||||
@@ -147,7 +147,6 @@ namespace ProjectSettingsTool
|
||||
// The process used to reconfigure settings
|
||||
QProcess m_reconfigureProcess;
|
||||
|
||||
AZStd::string m_devRoot;
|
||||
AZStd::string m_projectRoot;
|
||||
AZStd::string m_projectName;
|
||||
|
||||
|
||||
@@ -27,37 +27,31 @@ namespace
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
StringType GetAbsoluteDevRoot()
|
||||
StringType GetAbsoluteEngineRoot()
|
||||
{
|
||||
const char* devRoot = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
devRoot,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevRootFolderPath);
|
||||
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
|
||||
|
||||
if (!devRoot)
|
||||
if (engineRoot.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringType devRootString(devRoot);
|
||||
ToUnixPath(devRootString);
|
||||
return devRootString;
|
||||
StringType engineRootString(engineRoot.c_str());
|
||||
ToUnixPath(engineRootString);
|
||||
return engineRootString;
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
StringType GetAbsoluteProjectRoot()
|
||||
{
|
||||
const char* projectRoot = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
projectRoot,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevGameFolderPath);
|
||||
AZ::IO::FixedMaxPath projectRoot = AZ::Utils::GetProjectPath();
|
||||
|
||||
if (!projectRoot)
|
||||
if (projectRoot.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringType projectRootString(projectRoot);
|
||||
StringType projectRootString(projectRoot.c_str());
|
||||
ToUnixPath(projectRootString);
|
||||
return projectRootString;
|
||||
}
|
||||
@@ -87,9 +81,9 @@ namespace ProjectSettingsTool
|
||||
return reinterpret_cast<void*>(func);
|
||||
}
|
||||
|
||||
AZStd::string GetDevRoot()
|
||||
AZStd::string GetEngineRoot()
|
||||
{
|
||||
return GetAbsoluteDevRoot<AZStd::string>();
|
||||
return GetAbsoluteEngineRoot<AZStd::string>();
|
||||
}
|
||||
AZStd::string GetProjectRoot()
|
||||
{
|
||||
@@ -104,7 +98,7 @@ namespace ProjectSettingsTool
|
||||
QString SelectXmlFromFileDialog(const QString& currentFile)
|
||||
{
|
||||
// The selected file must be relative to this path
|
||||
QString defaultPath = GetAbsoluteDevRoot<QString>();
|
||||
QString defaultPath = GetAbsoluteEngineRoot<QString>();
|
||||
QString startPath;
|
||||
|
||||
// Choose the starting path for file dialog
|
||||
@@ -139,7 +133,7 @@ namespace ProjectSettingsTool
|
||||
|
||||
QString SelectImageFromFileDialog(const QString& currentFile)
|
||||
{
|
||||
QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteDevRoot<QString>(), ::GetProjectName<QString>());
|
||||
QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteEngineRoot<QString>(), ::GetProjectName<QString>());
|
||||
|
||||
QString startPath;
|
||||
|
||||
@@ -188,7 +182,7 @@ namespace ProjectSettingsTool
|
||||
// Android
|
||||
if (group <= ImageGroup::AndroidPortrait)
|
||||
{
|
||||
root = GetDevRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
|
||||
root = GetEngineRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
|
||||
}
|
||||
//Ios
|
||||
else
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace ProjectSettingsTool
|
||||
{
|
||||
void* ConvertFunctorToVoid(AZStd::pair<QValidator::State, const QString>(*func)(const QString&));
|
||||
AZStd::string GetDevRoot();
|
||||
AZStd::string GetEngineRoot();
|
||||
AZStd::string GetProjectRoot();
|
||||
AZStd::string GetProjectName();
|
||||
|
||||
|
||||
@@ -935,8 +935,9 @@ void SEditorSettings::LoadDefaultGamePaths()
|
||||
searchPaths[EDITOR_PATH_MATERIALS].push_back((Path::GetEditingGameDataFolder() + "/Materials").c_str());
|
||||
}
|
||||
|
||||
AZStd::string iconsPath;
|
||||
AZ::StringFunc::Path::Join(Path::GetEditingRootFolder().c_str(), "Editor/UI/Icons", iconsPath);
|
||||
auto iconsPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
|
||||
iconsPath /= "Editor/UI/Icons";
|
||||
iconsPath.MakePreferred();
|
||||
searchPaths[EDITOR_PATH_UI_ICONS].push_back(iconsPath.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
|
||||
// Enable/disable the 'remove'/'update' button properly.
|
||||
bool bNoSelection = !m_ui->m_renderList->selectionModel()->hasSelection();
|
||||
m_ui->BATCH_RENDER_REMOVE_SEQ->setEnabled(bNoSelection ? false : true);
|
||||
|
||||
|
||||
CheckForEnableUpdateButton();
|
||||
|
||||
if (bNoSelection)
|
||||
@@ -360,7 +360,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
|
||||
cvarsText += item.cvars[static_cast<int>(i)];
|
||||
cvarsText += "\r\n";
|
||||
}
|
||||
m_ui->m_cvarsEdit->setPlainText(cvarsText);
|
||||
m_ui->m_cvarsEdit->setPlainText(cvarsText);
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::CheckForEnableUpdateButton()
|
||||
@@ -494,7 +494,7 @@ void CSequenceBatchRenderDialog::OnSavePreset()
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::stashActiveViewportResolution()
|
||||
{
|
||||
{
|
||||
// stash active resolution in global vars
|
||||
activeViewportWidth = resolutions[0][0];
|
||||
activeViewportHeight = resolutions[0][1];
|
||||
@@ -502,7 +502,7 @@ void CSequenceBatchRenderDialog::stashActiveViewportResolution()
|
||||
if (activeViewport)
|
||||
{
|
||||
activeViewport->GetDimensions(&activeViewportWidth, &activeViewportHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::OnGo()
|
||||
@@ -640,7 +640,7 @@ void CSequenceBatchRenderDialog::OnResolutionSelected()
|
||||
int defaultH;
|
||||
const QString currentCustomResText = m_ui->m_resolutionCombo->currentText();
|
||||
GetResolutionFromCustomResText(currentCustomResText.toStdString().c_str(), defaultW, defaultH);
|
||||
|
||||
|
||||
CCustomResolutionDlg resDlg(defaultW, defaultH, this);
|
||||
if (resDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
@@ -752,7 +752,7 @@ bool CSequenceBatchRenderDialog::LoadOutputOptions(const QString& pathname)
|
||||
{
|
||||
const QString customResText = resolutionNode->getContent();
|
||||
m_ui->m_resolutionCombo->setItemText(curSel, customResText);
|
||||
|
||||
|
||||
GetResolutionFromCustomResText(customResText.toStdString().c_str(), m_customResW, m_customResH);
|
||||
}
|
||||
m_ui->m_resolutionCombo->setCurrentIndex(curSel);
|
||||
@@ -907,12 +907,12 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
|
||||
folder += "/";
|
||||
folder += itemText;
|
||||
|
||||
// If this is a relative path, prepend the @assets@ folder to match where the Renderer is going
|
||||
// If this is a relative path, prepend the @products@ folder to match where the Renderer is going
|
||||
// to dump the frame buffer image captures.
|
||||
if (AzFramework::StringFunc::Path::IsRelative(folder.toUtf8().data()))
|
||||
{
|
||||
AZStd::string absolutePath;
|
||||
AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@");
|
||||
AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@");
|
||||
AzFramework::StringFunc::Path::Join(assetsRoot.c_str(), folder.toUtf8().data(), absolutePath);
|
||||
folder = absolutePath.c_str();
|
||||
}
|
||||
@@ -962,7 +962,7 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
|
||||
m_renderContext.cvarDisplayInfoBU = cvarDebugInfo->GetIVal();
|
||||
if (renderItem.disableDebugInfo && cvarDebugInfo->GetIVal())
|
||||
{
|
||||
const int DISPLAY_INFO_OFF = 0;
|
||||
const int DISPLAY_INFO_OFF = 0;
|
||||
cvarDebugInfo->Set(DISPLAY_INFO_OFF);
|
||||
}
|
||||
}
|
||||
@@ -1100,13 +1100,13 @@ void CSequenceBatchRenderDialog::OnUpdateEnd(IAnimSequence* sequence)
|
||||
sequence->SetActiveDirector(m_renderContext.pActiveDirectorBU);
|
||||
|
||||
const auto imageFormat = m_ui->m_imageFormatCombo->currentText();
|
||||
|
||||
|
||||
SRenderItem renderItem = m_renderItems[m_renderContext.currentItemIndex];
|
||||
if (m_bFFMPEGCommandAvailable && renderItem.bCreateVideo)
|
||||
{
|
||||
// Create a video using the ffmpeg plug-in from captured images.
|
||||
m_renderContext.processingFFMPEG = true;
|
||||
|
||||
|
||||
AZStd::string outputFolder = m_renderContext.captureOptions.folder;
|
||||
auto future = QtConcurrent::run(
|
||||
[renderItem, outputFolder, imageFormat]
|
||||
@@ -1238,7 +1238,7 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout()
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::OnKickIdle()
|
||||
{
|
||||
{
|
||||
if (m_renderContext.captureState == CaptureState::WarmingUpAfterResChange)
|
||||
{
|
||||
OnUpdateWarmingUpAfterResChange();
|
||||
@@ -1254,7 +1254,7 @@ void CSequenceBatchRenderDialog::OnKickIdle()
|
||||
else if (m_renderContext.captureState == CaptureState::Capturing)
|
||||
{
|
||||
OnUpdateCapturing();
|
||||
}
|
||||
}
|
||||
else if (m_renderContext.captureState == CaptureState::End)
|
||||
{
|
||||
OnUpdateEnd(m_renderContext.endingSequence);
|
||||
|
||||
@@ -101,13 +101,13 @@ public:
|
||||
|
||||
if (fresh.size() < m_stackNames.size())
|
||||
{
|
||||
beginRemoveRows(createIndex(-1, -1), static_cast<int>(fresh.size()), static_cast<int>(m_stackNames.size() - 1));
|
||||
beginRemoveRows(QModelIndex(), static_cast<int>(fresh.size()), static_cast<int>(m_stackNames.size() - 1));
|
||||
m_stackNames = fresh;
|
||||
endRemoveRows();
|
||||
}
|
||||
else
|
||||
{
|
||||
beginInsertRows(createIndex(-1, -1), static_cast<int>(m_stackNames.size()), static_cast<int>(fresh.size() - 1));
|
||||
beginInsertRows(QModelIndex(), static_cast<int>(m_stackNames.size()), static_cast<int>(fresh.size() - 1));
|
||||
m_stackNames = fresh;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
+33
-167
@@ -11,9 +11,9 @@
|
||||
|
||||
#include "PathUtil.h"
|
||||
|
||||
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for ebus events
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
@@ -179,7 +179,7 @@ namespace Path
|
||||
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
|
||||
return QString(engineRoot);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString& ReplaceFilename(const QString& strFilepath, const QString& strFilename, QString& strOutputFilename, bool bCallCaselessPath)
|
||||
{
|
||||
@@ -216,30 +216,21 @@ namespace Path
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString GetResolvedUserSandboxFolder()
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
gEnv->pFileIO->ResolvePath(GetUserSandboxFolder().toUtf8().data(), resolvedPath, AZ_MAX_PATH_LEN);
|
||||
return QString::fromLatin1(resolvedPath);
|
||||
AZ::IO::FixedMaxPath userSandboxFolderPath;
|
||||
gEnv->pFileIO->ResolvePath(userSandboxFolderPath, GetUserSandboxFolder().toUtf8().constData());
|
||||
return QString::fromUtf8(userSandboxFolderPath.c_str(), static_cast<int>(userSandboxFolderPath.Native().size()));
|
||||
}
|
||||
|
||||
// internal function, you should use GetEditingGameDataFolder instead.
|
||||
AZStd::string GetGameAssetsFolder()
|
||||
{
|
||||
const char* resultValue = nullptr;
|
||||
EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevGameFolderPath);
|
||||
if (!resultValue)
|
||||
AZ::IO::Path projectPath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if ((gEnv) && (gEnv->pFileIO))
|
||||
{
|
||||
resultValue = gEnv->pFileIO->GetAlias("@devassets@");
|
||||
}
|
||||
settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath);
|
||||
}
|
||||
|
||||
if (!resultValue)
|
||||
{
|
||||
resultValue = ".";
|
||||
}
|
||||
|
||||
return resultValue;
|
||||
return projectPath.Native();
|
||||
}
|
||||
|
||||
/// Get the data folder
|
||||
@@ -258,26 +249,6 @@ namespace Path
|
||||
return str;
|
||||
}
|
||||
|
||||
//! Get the root folder (in source control or other writable assets) where you should save root data.
|
||||
AZStd::string GetEditingRootFolder()
|
||||
{
|
||||
const char* resultValue = nullptr;
|
||||
EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevRootFolderPath);
|
||||
|
||||
if (!resultValue)
|
||||
{
|
||||
if ((gEnv) && (gEnv->pFileIO))
|
||||
{
|
||||
resultValue = gEnv->pFileIO->GetAlias("@devassets@");
|
||||
}
|
||||
}
|
||||
if (!resultValue)
|
||||
{
|
||||
resultValue = ".";
|
||||
}
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
|
||||
AZStd::string MakeModPathFromGamePath(const char* relGamePath)
|
||||
{
|
||||
@@ -335,165 +306,60 @@ namespace Path
|
||||
return "";
|
||||
}
|
||||
|
||||
bool relPathfound = false;
|
||||
bool relPathFound = false;
|
||||
AZStd::string relativePath;
|
||||
AZStd::string fullAssetPath(fullPath.toUtf8().data());
|
||||
EBUS_EVENT_RESULT(relPathfound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
|
||||
EBUS_EVENT_RESULT(relPathFound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
|
||||
|
||||
if (relPathfound)
|
||||
if (relPathFound)
|
||||
{
|
||||
// do not normalize this path, it will already be an appropriate asset ID.
|
||||
return CaselessPaths(relativePath.c_str());
|
||||
}
|
||||
|
||||
char rootpath[_MAX_PATH] = { 0 };
|
||||
azstrcpy(rootpath, _MAX_PATH, Path::GetEditingRootFolder().c_str());
|
||||
|
||||
if (bRelativeToGameFolder)
|
||||
{
|
||||
azstrcpy(rootpath, _MAX_PATH, Path::GetEditingGameDataFolder().c_str());
|
||||
}
|
||||
|
||||
QString rootPathNormalized(rootpath);
|
||||
QString srcPathNormalized(fullPath);
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// avoid confusing PathRelativePathTo
|
||||
rootPathNormalized.replace('/', '\\');
|
||||
srcPathNormalized.replace('/', '\\');
|
||||
#endif
|
||||
AZ::IO::FixedMaxPath rootPath = bRelativeToGameFolder ? AZ::Utils::GetProjectPath() : AZ::Utils::GetEnginePath();
|
||||
AZ::IO::FixedMaxPath resolvedFullPath;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedFullPath, fullPath.toUtf8().constData());
|
||||
|
||||
// Create relative path
|
||||
char resolvedSrcPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(srcPathNormalized.toUtf8().data(), resolvedSrcPath, AZ_MAX_PATH_LEN);
|
||||
QByteArray path = QDir(rootPathNormalized).relativeFilePath(resolvedSrcPath).toUtf8();
|
||||
if (path.isEmpty())
|
||||
{
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
// The following code is required because the windows PathRelativePathTo function will always return "./SomePath" instead of just "SomePath"
|
||||
// Only remove single dot (.) and slash parts of a path, never the double dot (..)
|
||||
const char* pBuffer = path.data();
|
||||
bool bHasDot = false;
|
||||
while (*pBuffer && pBuffer != path.end())
|
||||
{
|
||||
switch (*pBuffer)
|
||||
{
|
||||
case '.':
|
||||
if (bHasDot)
|
||||
{
|
||||
// Found a double dot, rewind and stop removing
|
||||
pBuffer--;
|
||||
break;
|
||||
}
|
||||
// Fall through intended
|
||||
case '/':
|
||||
case '\\':
|
||||
bHasDot = (*pBuffer == '.');
|
||||
pBuffer++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
QString relPath = pBuffer;
|
||||
return CaselessPaths(relPath);
|
||||
return CaselessPaths(resolvedFullPath.LexicallyProximate(rootPath).MakePreferred().c_str());
|
||||
}
|
||||
|
||||
QString GamePathToFullPath(const QString& path)
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
AZ_Warning("GamePathToFullPath", path.size() <= AZ_MAX_PATH_LEN, "Path exceeds maximum path length of %d", AZ_MAX_PATH_LEN);
|
||||
if ((gEnv) && (gEnv->pFileIO) && gEnv->pCryPak && path.size() <= AZ_MAX_PATH_LEN)
|
||||
AZ_Warning("GamePathToFullPath", path.size() <= AZ::IO::MaxPathLength, "Path exceeds maximum path length of %zu", AZ::IO::MaxPathLength);
|
||||
if (path.size() <= AZ::IO::MaxPathLength)
|
||||
{
|
||||
// first, adjust the file name for mods:
|
||||
bool fullPathfound = false;
|
||||
AZStd::string assetFullPath;
|
||||
AZStd::string adjustedFilePath = path.toUtf8().data();
|
||||
AssetSystemRequestBus::BroadcastResult(fullPathfound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, adjustedFilePath, assetFullPath);
|
||||
if (fullPathfound)
|
||||
bool fullPathFound = false;
|
||||
AZ::IO::Path assetFullPath;
|
||||
AZ::IO::Path adjustedFilePath = path.toUtf8().constData();
|
||||
AssetSystemRequestBus::BroadcastResult(fullPathFound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath,
|
||||
adjustedFilePath.Native(), assetFullPath.Native());
|
||||
if (fullPathFound)
|
||||
{
|
||||
//if the bus message succeeds than normalize and lowercase the path
|
||||
AzFramework::StringFunc::Path::Normalize(assetFullPath);
|
||||
return assetFullPath.c_str();
|
||||
//if the bus message succeeds than normalize
|
||||
return assetFullPath.LexicallyNormal().c_str();
|
||||
}
|
||||
// if the bus message didn't succeed, 'guess' the source assets:
|
||||
// if the bus message didn't succeed, check if he path exist as a resolved path
|
||||
else
|
||||
{
|
||||
// Not all systems have been converted to use local paths. Some editor files save XML files directly, and a full or correctly aliased path is already passed in.
|
||||
// If the path passed in exists already, then return the resolved filepath
|
||||
if (AZ::IO::FileIOBase::GetDirectInstance()->Exists(adjustedFilePath.c_str()))
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(adjustedFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength);
|
||||
return QString::fromUtf8(resolvedPath);
|
||||
AZ::IO::FixedMaxPath resolvedPath;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, adjustedFilePath);
|
||||
return QString::fromUtf8(resolvedPath.c_str(), static_cast<int>(resolvedPath.Native().size()));
|
||||
}
|
||||
// if we get here it means that the Asset Processor does not know about this file. most of the time we should never get here
|
||||
// the rest of this code just does a bunch of heuristic guesses in case of missing files or if the user has hand-edited
|
||||
// the asset cache by moving files in via some other means or external process.
|
||||
if (adjustedFilePath[0] != '@')
|
||||
{
|
||||
const char* prefix = (adjustedFilePath[0] == '/' || adjustedFilePath[0] == '\\') ? "@devassets@" : "@devassets@/";
|
||||
adjustedFilePath = prefix + adjustedFilePath;
|
||||
}
|
||||
|
||||
char szAdjustedFile[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
gEnv->pFileIO->ResolvePath(adjustedFilePath.c_str(), szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile));
|
||||
|
||||
if ((azstrnicmp(szAdjustedFile, "@devassets@", 11) == 0) && ((szAdjustedFile[11] == '/') || (szAdjustedFile[11] == '\\')))
|
||||
{
|
||||
if (!gEnv->pCryPak->IsFileExist(szAdjustedFile))
|
||||
{
|
||||
AZStd::string newName(szAdjustedFile);
|
||||
AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@/engine", false);
|
||||
|
||||
if (gEnv->pCryPak->IsFileExist(newName.c_str()))
|
||||
{
|
||||
azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// getting tricky here, try @devroot@ alone, in case its 'editor'
|
||||
AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@", false);
|
||||
if (gEnv->pCryPak->IsFileExist(szAdjustedFile))
|
||||
{
|
||||
azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
|
||||
}
|
||||
// give up, best guess is just @devassets@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we should very rarely actually get to this point in the code.
|
||||
|
||||
// szAdjustedFile may contain an alias at this point. (@assets@/blah.whatever)
|
||||
// there is a case in which the loose asset exists only within a pak file for some reason
|
||||
// this is not recommended but it is possible.in that case, we want to return the original szAdjustedFile
|
||||
// without touching it or resolving it so that crypak can open it successfully.
|
||||
char adjustedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
if (gEnv->pFileIO->ResolvePath(szAdjustedFile, adjustedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength)) // resolve to full path
|
||||
{
|
||||
if ((gEnv->pCryPak->IsFileExist(adjustedPath)) || (!gEnv->pCryPak->IsFileExist(szAdjustedFile)))
|
||||
{
|
||||
// note that if we get here, then EITHER
|
||||
// the file exists as a loose asset in the actual adjusted path
|
||||
// OR the file does not exist in the original passed-in aliased name (like '@assets@/whatever')
|
||||
// in which case we may as well just resolve the path to a full path and return it.
|
||||
assetFullPath = adjustedPath;
|
||||
AzFramework::StringFunc::Path::Normalize(assetFullPath);
|
||||
azstrcpy(szAdjustedFile, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength, assetFullPath.c_str());
|
||||
}
|
||||
// if the above case succeeded then it means that the file does NOT exist loose
|
||||
// but DOES exist in a pak, in which case we leave szAdjustedFile with the alias on the front of it, meaning
|
||||
// fopens via crypak will actually succeed.
|
||||
}
|
||||
return szAdjustedFile;
|
||||
return path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
return QString{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ namespace Path
|
||||
//! always returns a full path
|
||||
EDITOR_CORE_API AZStd::string GetEditingGameDataFolder();
|
||||
|
||||
//! Get the root folder (in source control or other writable assets) where you should save root data.
|
||||
EDITOR_CORE_API AZStd::string GetEditingRootFolder();
|
||||
|
||||
//! Set the current mod NAME for editing purposes. After doing this the above functions will take this into account
|
||||
//! name only, please!
|
||||
EDITOR_CORE_API void SetModName(const char* input);
|
||||
@@ -69,93 +66,6 @@ namespace Path
|
||||
return strPath;
|
||||
}
|
||||
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param file [OUT] Extracted file (with extension).
|
||||
inline void Split(const QString& filepath, QString& path, QString& file)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
|
||||
#else
|
||||
_splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath(path_buffer, 0, 0, fname, ext);
|
||||
#endif
|
||||
file = path_buffer;
|
||||
}
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
|
||||
#else
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath(path_buffer, 0, 0, fname, ext);
|
||||
#endif
|
||||
file = path_buffer;
|
||||
}
|
||||
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param filename [OUT] Extracted file (without extension).
|
||||
//! @param ext [OUT] Extracted files extension.
|
||||
inline void Split(const QString& filepath, QString& path, QString& filename, QString& fext)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
#else
|
||||
_splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
#endif
|
||||
path = path_buffer;
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
#else
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
#endif
|
||||
path = path_buffer;
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
|
||||
//! Split path into segments
|
||||
//! @param filepath [IN] path
|
||||
inline QStringList SplitIntoSegments(const QString& path)
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
|
||||
virtual Vec3 SnapToGrid(const Vec3& vec) = 0;
|
||||
|
||||
//! Get selection procision tolerance.
|
||||
//! Get selection precision tolerance.
|
||||
virtual float GetSelectionTolerance() const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace AZ
|
||||
virtual AZ::u64 ModificationTime(HandleType fileHandle) = 0;
|
||||
virtual AZ::u64 ModificationTime(const char* filePath) = 0;
|
||||
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
virtual Result Size(const char* filePath, AZ::u64& size) = 0;
|
||||
virtual Result Size(HandleType fileHandle, AZ::u64& size) = 0;
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace AZ
|
||||
/// note: the callback will contain the full concatenated path (filePath + slash + fileName)
|
||||
/// not just the individual file name found.
|
||||
/// note: if the file path of the found file corresponds to a registered ALIAS, the longest matching alias will be returned
|
||||
/// so expect return values like @assets@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// so expect return values like @products@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// note: if rootPath is specified the implementation has the option of substituting it for the current directory
|
||||
/// as would be the case on a file server.
|
||||
typedef AZStd::function<bool(const char*)> FindFilesCallbackType;
|
||||
@@ -206,13 +206,18 @@ namespace AZ
|
||||
|
||||
// Alias system
|
||||
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @root@, etc.
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @products@, etc.
|
||||
virtual void SetAlias(const char* alias, const char* path) = 0;
|
||||
/// ClearAlias - Removes an alias from the path resolution system
|
||||
virtual void ClearAlias(const char* alias) = 0;
|
||||
/// GetAlias - Returns the destination path for a given alias, or nullptr if the alias does not exist
|
||||
virtual const char* GetAlias(const char* alias) const = 0;
|
||||
|
||||
/// SetDeprecateAlias - Adds a deprecated alias with path resolution which points to a new alias
|
||||
/// When the DeprecatedAlias is used an Error is logged and the alias is resolved to the path
|
||||
/// specified by the new alais
|
||||
virtual void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) = 0;
|
||||
|
||||
/// Shorten the given path if it contains an alias. it will always pick the longest alias match.
|
||||
/// note that it re-uses the buffer, since the data can only get smaller and we don't want to internally allocate memory if we
|
||||
/// can avoid it.
|
||||
@@ -230,8 +235,8 @@ namespace AZ
|
||||
|
||||
//! ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
|
||||
//! also ensures that the path is absolute
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @assets@ is used
|
||||
//! which has the effect of making the path relative to the @assets@/ folder
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @products@ is used
|
||||
//! which has the effect of making the path relative to the @products@/ folder
|
||||
//! returns true if path was resolved, false otherwise
|
||||
//! note that all of the above file-finding and opening functions automatically resolve the path before operating
|
||||
//! so you should not need to call this except in very exceptional circumstances where you absolutely need to
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace AZ::IO
|
||||
// These functions can't be called after a request has been queued.
|
||||
//
|
||||
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -62,9 +62,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -84,8 +84,8 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -106,9 +106,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -138,7 +138,7 @@ namespace AZ::IO
|
||||
//! @result A smart pointer to the newly created request with the cancel command.
|
||||
virtual FileRequestPtr Cancel(FileRequestPtr target) = 0;
|
||||
|
||||
//! Sets a request to the cancel command.
|
||||
//! Sets a request to the cancel command.
|
||||
//! When this request completes it's not guaranteed to have canceled the target request. Not all requests can be canceled and requests
|
||||
//! that already processing may complete. It's recommended to let the target request handle the completion of the request as normal
|
||||
//! and handle cancellation by checking the status on the target request is set to IStreamerTypes::RequestStatus::Canceled.
|
||||
@@ -177,7 +177,7 @@ namespace AZ::IO
|
||||
//! DestroyDedicatedCache is called. Typical use of a dedicated cache is for files that have their own compression
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to create a dedicated cache.
|
||||
virtual FileRequestPtr CreateDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -186,25 +186,25 @@ namespace AZ::IO
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param request The request that will store the command to create a dedicated cache.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& CreateDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to destroy a dedicated cache.
|
||||
virtual FileRequestPtr DestroyDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param request The request that will store the command to destroy a dedicated cache.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& DestroyDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Clears a file from all caches in use by Streamer.
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to flush a file from all caches.
|
||||
virtual FileRequestPtr FlushCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace AZ::IO
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param request The request that will store the command to flush a file from all caches.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& FlushCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace AZ::IO
|
||||
//
|
||||
|
||||
//! Collect statistics from all the components that make up Streamer.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! Data is collected lockless from involved threads and might be slightly
|
||||
//! out of date in some cases.
|
||||
//! @param statistics The container where statistics will be added to.
|
||||
|
||||
@@ -98,6 +98,11 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const noexcept;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// decomposition
|
||||
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
|
||||
//! "/O3DE/foo/bar/name.txt"
|
||||
@@ -178,7 +183,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -238,7 +243,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
@@ -253,24 +258,23 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
friend class BasicPath;
|
||||
friend struct AZStd::hash<PathView>;
|
||||
|
||||
template <typename PathResultType>
|
||||
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
|
||||
|
||||
struct PathIterable;
|
||||
|
||||
static constexpr void MakeRelativeTo(PathIterable& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept;
|
||||
|
||||
//! Returns a structure that provides a view of the path parts which can be used for iteration
|
||||
//! Only the path parts that correspond to creating an normalized path is returned
|
||||
//! This function is useful for returning a "view" into a normalized path without the need
|
||||
//! to allocate memory for the heap
|
||||
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
|
||||
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
// If the input path is absolute it will replace the current PathIterable otherwise
|
||||
// the input path will be appended to the Path Iterable structure
|
||||
// For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
//! joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
//! If the input path is absolute it will replace the current PathIterable otherwise
|
||||
//! the input path will be appended to the Path Iterable structure
|
||||
//! For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
//! If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
//! If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
//! If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
//! If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
|
||||
|
||||
constexpr int ComparePathView(const PathView& other) const;
|
||||
@@ -325,32 +329,32 @@ namespace AZ::IO
|
||||
constexpr BasicPath(BasicPath&& other) = default;
|
||||
|
||||
// Conversion constructor for other types of BasicPath instantiations
|
||||
constexpr BasicPath(const PathView& other);
|
||||
constexpr BasicPath(const PathView& other) noexcept;
|
||||
|
||||
// String constructors
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const string_type& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const string_type& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by moving the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(string_type&& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(string_type&& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(AZStd::string_view src) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separators it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(AZStd::string_view src, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const value_type* pathString) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const value_type* pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a empty Path with the preferred separator set to the parameter
|
||||
explicit constexpr BasicPath(const char preferredSeparator) noexcept;
|
||||
@@ -371,7 +375,7 @@ namespace AZ::IO
|
||||
constexpr BasicPath& operator=(BasicPath&& other) = default;
|
||||
|
||||
// conversion assignment operator
|
||||
constexpr BasicPath& operator=(const PathView& pathView);
|
||||
constexpr BasicPath& operator=(const PathView& pathView) noexcept;
|
||||
constexpr BasicPath& operator=(const string_type& str) noexcept;
|
||||
constexpr BasicPath& operator=(string_type&& str) noexcept;
|
||||
constexpr BasicPath& operator=(AZStd::string_view str) noexcept;
|
||||
@@ -477,6 +481,12 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
AZStd::string StringAsPosix() const;
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// compare
|
||||
//! Performs a compare of each of the path parts for equivalence
|
||||
//! Each part of the path is compare using string comparison
|
||||
@@ -574,7 +584,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -616,7 +626,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
|
||||
@@ -240,6 +240,14 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
// decomposition
|
||||
constexpr auto PathView::RootName() const -> PathView
|
||||
{
|
||||
@@ -473,8 +481,7 @@ namespace AZ::IO
|
||||
return lhs.Compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
template <typename PathResultType>
|
||||
constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base)
|
||||
constexpr void PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept
|
||||
{
|
||||
const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator
|
||||
|| base.m_preferred_separator == PosixPathSeparator;
|
||||
@@ -492,13 +499,11 @@ namespace AZ::IO
|
||||
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare);
|
||||
res != 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,7 +517,6 @@ namespace AZ::IO
|
||||
}
|
||||
if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -530,7 +534,7 @@ namespace AZ::IO
|
||||
// If there is no mismatch, return ".".
|
||||
if (!pathParser && !pathParserBase)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,27 +543,25 @@ namespace AZ::IO
|
||||
int elemCount = parser::DetermineLexicalElementCount(pathParserBase);
|
||||
if (elemCount < 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
// if elemCount == 0 and (pathParser == end() || pathParser->empty()), returns path("."); otherwise
|
||||
if (elemCount == 0 && (pathParser.AtEnd() || *pathParser == ""))
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
// return a path constructed with 'n' dot-dot elements, followed by the
|
||||
// elements of '*this' after the mismatch.
|
||||
pathResult = PathResultType(path.m_preferred_separator);
|
||||
while (elemCount--)
|
||||
{
|
||||
pathResult /= "..";
|
||||
pathIterable.emplace_back("..", parser::PathPartKind::PK_DotDot);
|
||||
}
|
||||
for (; pathParser; ++pathParser)
|
||||
{
|
||||
pathResult /= *pathParser;
|
||||
pathIterable.emplace_back(*pathParser, parser::ClassifyPathPart(pathParser));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +675,7 @@ namespace AZ::IO
|
||||
// Basic Path implementation
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other)
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other) noexcept
|
||||
: m_path(other.m_path)
|
||||
, m_preferred_separator(other.m_preferred_separator) {}
|
||||
|
||||
@@ -726,6 +728,7 @@ namespace AZ::IO
|
||||
: m_path(first, last)
|
||||
, m_preferred_separator(preferredSeparator) {}
|
||||
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::operator PathView() const noexcept
|
||||
{
|
||||
@@ -733,7 +736,7 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) -> BasicPath&
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) noexcept -> BasicPath&
|
||||
{
|
||||
m_path = other.m_path;
|
||||
m_preferred_separator = other.m_preferred_separator;
|
||||
@@ -974,13 +977,13 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::MakePreferred() -> BasicPath&
|
||||
{
|
||||
if (m_preferred_separator != '/')
|
||||
if (m_preferred_separator != PosixPathSeparator)
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '/', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), PosixPathSeparator, m_preferred_separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '\\', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), WindowsPathSeparator, m_preferred_separator);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1033,6 +1036,24 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
// Returns a copy of the path with the path separators converted to PosixPathSeparator
|
||||
template <typename StringType>
|
||||
AZStd::string BasicPath<StringType>::StringAsPosix() const
|
||||
{
|
||||
AZStd::string resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr AZStd::fixed_string<MaxPathLength> BasicPath<StringType>::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr void BasicPath<StringType>::swap(BasicPath& rhs) noexcept
|
||||
{
|
||||
@@ -1234,6 +1255,7 @@ namespace AZ::IO
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1263,13 @@ namespace AZ::IO
|
||||
constexpr auto BasicPath<StringType>::LexicallyRelative(const PathView& base) const -> BasicPath
|
||||
{
|
||||
BasicPath pathResult(m_preferred_separator);
|
||||
static_cast<PathView>(*this).MakeRelativeTo(pathResult, *this, base);
|
||||
PathView::PathIterable pathIterable;
|
||||
PathView::MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1383,7 @@ namespace AZ::IO
|
||||
return !basePathParts.empty() || !thisPathParts.IsAbsolute();
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyNormal() const
|
||||
constexpr auto PathView::LexicallyNormal() const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
PathIterable pathIterable = GetNormalPathParts(*this);
|
||||
@@ -1367,21 +1395,28 @@ namespace AZ::IO
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyRelative(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyRelative(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
MakeRelativeTo(pathResult, *this, base);
|
||||
PathIterable pathIterable;
|
||||
MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyProximate(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyProximate(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath result = LexicallyRelative(base);
|
||||
if (result.empty())
|
||||
FixedMaxPath pathResult = LexicallyRelative(base);
|
||||
if (pathResult.empty())
|
||||
{
|
||||
return FixedMaxPath(*this);
|
||||
}
|
||||
return result;
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace AZ::IO
|
||||
|
||||
constexpr void clear() noexcept;
|
||||
|
||||
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
|
||||
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
|
||||
friend constexpr auto PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView&, const AZ::IO::PathView&) noexcept -> void;
|
||||
PartKindArray m_parts{};
|
||||
size_t m_size{};
|
||||
};
|
||||
|
||||
@@ -276,7 +276,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return engineRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Fall back to using the project root as the engine root if the engine path could not be reconciled
|
||||
// by checking the project.json "engine" string within o3de_manifest.json "engine_paths" object
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
|
||||
@@ -309,7 +311,13 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Step 3 Check for a "Cache" directory by scanning upwards from the executable directory
|
||||
if (auto candidateRoot = Internal::ScanUpRootLocator("Cache");
|
||||
!candidateRoot.empty() && AZ::IO::SystemFile::IsDirectory(candidateRoot.c_str()))
|
||||
{
|
||||
projectRoot = AZStd::move(candidateRoot);
|
||||
}
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZStd::string_view ConfigParserSettings::DefaultCommentPrefixFilter(AZStd::string_view line)
|
||||
@@ -538,7 +546,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
|
||||
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
|
||||
|
||||
// Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
|
||||
// Engine root folder - corresponds to the @engroot@ and @engroot@ aliases
|
||||
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
|
||||
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
|
||||
|
||||
@@ -562,7 +570,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
}
|
||||
|
||||
// Project path - corresponds to the @devassets@ alias
|
||||
// Project path - corresponds to the @projectroot@ alias
|
||||
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
|
||||
path = engineRoot / projectPathValue;
|
||||
|
||||
@@ -654,7 +662,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache: root - same as the @root@ alias, this is the starting path for cache files.
|
||||
// Cache: root - same as the @products@ alias, this is the starting path for cache files.
|
||||
path = normalizedProjectPath / "Cache";
|
||||
registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
|
||||
path /= assetPlatform;
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
MOCK_METHOD2(SetAlias, void(const char* alias, const char* path));
|
||||
MOCK_METHOD1(ClearAlias, void(const char* alias));
|
||||
MOCK_CONST_METHOD1(GetAlias, const char*(const char* alias));
|
||||
MOCK_METHOD2(SetDeprecatedAlias, void(AZStd::string_view, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, AZStd::optional<AZ::u64>(char* inOutBuffer, AZ::u64 bufferLength));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
|
||||
MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
|
||||
|
||||
@@ -51,6 +51,20 @@ namespace AZ::Utils
|
||||
return executableDirectory;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (ConvertToAbsolutePath(srcPath.c_str(), absolutePath.data(), absolutePath.capacity()))
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
{
|
||||
AZ::IO::FixedMaxPath o3deManifestPath = GetO3deManifestDirectory();
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace AZ
|
||||
// Attempts the supplied path to an absolute path.
|
||||
//! Returns nullopt if path cannot be converted to an absolute path
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path);
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 absolutePathMaxSize);
|
||||
|
||||
//! Save a string to a file. Otherwise returns a failure with error message.
|
||||
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
|
||||
|
||||
@@ -39,7 +39,7 @@ ly_add_target(
|
||||
3rdParty::Lua
|
||||
3rdParty::RapidJSON
|
||||
3rdParty::RapidXML
|
||||
3rdParty::zlib
|
||||
3rdParty::ZLIB
|
||||
3rdParty::zstd
|
||||
3rdParty::cityhash
|
||||
${AZ_CORE_PIX_BUILD_DEPENDENCIES}
|
||||
|
||||
@@ -60,23 +60,34 @@ namespace AZ
|
||||
return writeStorage ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(writeStorage) : AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
|
||||
if (AZ::Android::Utils::IsApkPath(path))
|
||||
{
|
||||
return srcPath;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,23 +47,32 @@ namespace AZ
|
||||
AZ::IO::FixedMaxPath path{pass->pw_dir};
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
|
||||
if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
} // namespace Utils
|
||||
} // namespace AZ
|
||||
|
||||
@@ -67,19 +67,12 @@ namespace AZ
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
|
||||
// Force update of the fixed_string size() value
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
if (result)
|
||||
{
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
char* result = _fullpath(absolutePath, path, maxLength);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +426,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetDeprecatedAlias(AZStd::string_view, AZStd::string_view) override
|
||||
{
|
||||
}
|
||||
|
||||
void ClearAlias(const char* ) override { }
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64) const override
|
||||
|
||||
@@ -698,7 +698,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
using PathViewLexicallyProximateFixture = PathLexicallyFixture<PathViewLexicallyProximateParams>;
|
||||
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPathIfNot)
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPath)
|
||||
{
|
||||
const auto& testParams = GetParam();
|
||||
AZ::IO::PathView testPath(testParams.m_testPathString, testParams.m_preferredSeparator);
|
||||
|
||||
@@ -77,11 +77,15 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
namespace ApplicationInternal
|
||||
{
|
||||
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
|
||||
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
|
||||
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
|
||||
static constexpr const char* DeprecatedFileIOAliasesRoot = "/O3DE/AzCore/FileIO/DeprecatedAliases";
|
||||
static constexpr const char* DeprecatedFileIOAliasesOldAliasKey = "OldAlias";
|
||||
static constexpr const char* DeprecatedFileIOAliasesNewAliasKey = "NewAlias";
|
||||
}
|
||||
|
||||
Application::Application()
|
||||
@@ -563,6 +567,68 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
struct DeprecatedAliasesKeyVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view,
|
||||
VisitAction action, Type type) override
|
||||
{
|
||||
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = path;
|
||||
}
|
||||
|
||||
// Strip off last path segment from json path and check if is a child element of the array
|
||||
if (AZ::StringFunc::TokenizeLast(path, '/');
|
||||
m_parentArrayPath == path)
|
||||
{
|
||||
m_aliases.emplace_back();
|
||||
}
|
||||
}
|
||||
else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = AZStd::string{};
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
void Visit(AZStd::string_view, AZStd::string_view valueName, Type, AZStd::string_view value) override
|
||||
{
|
||||
if (!m_aliases.empty())
|
||||
{
|
||||
if (valueName == ApplicationInternal::DeprecatedFileIOAliasesOldAliasKey)
|
||||
{
|
||||
m_aliases.back().m_oldAlias = value;
|
||||
}
|
||||
else if (valueName == ApplicationInternal::DeprecatedFileIOAliasesNewAliasKey)
|
||||
{
|
||||
m_aliases.back().m_newAlias = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AliasPair
|
||||
{
|
||||
AZStd::string m_oldAlias;
|
||||
AZStd::string m_newAlias;
|
||||
};
|
||||
AZStd::vector<AliasPair> m_aliases;
|
||||
|
||||
private:
|
||||
AZStd::string m_parentArrayPath;
|
||||
};
|
||||
|
||||
static void CreateUserCache(const AZ::IO::FixedMaxPath& cacheUserPath, AZ::IO::FileIOBase& fileIoBase)
|
||||
{
|
||||
@@ -610,9 +676,8 @@ namespace AzFramework
|
||||
|
||||
void Application::SetFileIOAliases()
|
||||
{
|
||||
if (m_archiveFileIO)
|
||||
if (auto fileIoBase = m_archiveFileIO.get(); fileIoBase)
|
||||
{
|
||||
auto fileIoBase = m_archiveFileIO.get();
|
||||
// Set up the default file aliases based on the settings registry
|
||||
fileIoBase->SetAlias("@engroot@", GetEngineRoot());
|
||||
fileIoBase->SetAlias("@projectroot@", GetEngineRoot());
|
||||
@@ -620,29 +685,20 @@ namespace AzFramework
|
||||
|
||||
{
|
||||
AZ::IO::FixedMaxPath pathAliases;
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@projectcache@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@root@", pathAliases.c_str()); // Deprecated Use @projectplatformcache@
|
||||
fileIoBase->SetAlias("@products@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@engroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@devroot@", pathAliases.c_str()); // Deprecated - Use @engroot@
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
||||
{
|
||||
fileIoBase->SetAlias("@devassets@", pathAliases.c_str()); // Deprecated - Use @projectsourceassets@
|
||||
fileIoBase->SetAlias("@projectroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectsourceassets@", (pathAliases / "Assets").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +719,15 @@ namespace AzFramework
|
||||
}
|
||||
fileIoBase->SetAlias("@log@", projectLogPath.c_str());
|
||||
fileIoBase->CreatePath(projectLogPath.c_str());
|
||||
|
||||
DeprecatedAliasesKeyVisitor visitor;
|
||||
if (m_settingsRegistry->Visit(visitor, ApplicationInternal::DeprecatedFileIOAliasesRoot))
|
||||
{
|
||||
for (const auto& [oldAlias, newAlias] : visitor.m_aliases)
|
||||
{
|
||||
fileIoBase->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ namespace AZ::IO
|
||||
|
||||
if (AZ::IO::FixedMaxPath pathBindRoot; !AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, szBindRoot))
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@assets@");
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@products@");
|
||||
desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String();
|
||||
}
|
||||
else
|
||||
@@ -1807,9 +1807,9 @@ namespace AZ::IO
|
||||
if (m_eRecordFileOpenList != IArchive::RFOM_Disabled)
|
||||
{
|
||||
// we only want to record ASSET access
|
||||
// assets are identified as files that are relative to the resolved @assets@ alias path
|
||||
// assets are identified as files that are relative to the resolved @products@ alias path
|
||||
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
|
||||
const char* aliasValue = fileIoBase->GetAlias("@assets@");
|
||||
const char* aliasValue = fileIoBase->GetAlias("@products@");
|
||||
|
||||
if (AZ::IO::FixedMaxPath resolvedFilePath;
|
||||
fileIoBase->ResolvePath(resolvedFilePath, szFilename)
|
||||
|
||||
@@ -546,6 +546,16 @@ namespace AZ::IO
|
||||
realUnderlyingFileIO->GetAlias(alias);
|
||||
}
|
||||
|
||||
void ArchiveFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
FileIOBase* realUnderlyingFileIO = FileIOBase::GetDirectInstance();
|
||||
if (!realUnderlyingFileIO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
realUnderlyingFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> ArchiveFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
if ((!inOutBuffer) || (bufferLength == 0))
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ::IO
|
||||
IO::Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace AZ::IO
|
||||
{
|
||||
// filter out the stuff which does not match.
|
||||
|
||||
// the problem here is that szDir might be something like "@assets@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@assets@" or "@assets@/levels/mylevel"
|
||||
// the problem here is that szDir might be something like "@products@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@products@" or "@products@/levels/mylevel"
|
||||
// so there's really no way to filter out opening the pack and looking at the files inside.
|
||||
// however, the bind root is not part of the inner zip entry name either
|
||||
// and the ZipDir::FindFile actually expects just the chopped off piece.
|
||||
@@ -202,22 +202,22 @@ namespace AZ::IO
|
||||
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\" <--- mount point
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\" <--- mount point
|
||||
// ~~~~~~~~~~~ Common part
|
||||
// "levels\\*" <---- remainder that is not in common
|
||||
// "" <--- mount point remainder. In this case, we should scan the contents of the pak for the remainder
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// ~~~~~~~~~~~~~~~~~~ common part
|
||||
// "*" <---- remainder that is not in common
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
// example:
|
||||
// "@assets@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "otherlevel\\*" <---- remainder
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace AZ::IO
|
||||
// which means we may search inside the pack.
|
||||
ScanInZip(it->pZip.get(), sourcePathRemainder.Native());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace AZ::IO::Internal
|
||||
}
|
||||
|
||||
AZStd::smatch matches;
|
||||
const AZStd::regex lodRegex("@assets@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
const AZStd::regex lodRegex("@products@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
if (!AZStd::regex_match(szPath, matches, lodRegex) || matches.size() != 3)
|
||||
{
|
||||
// The current file is not a valid LOD file
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace AzFramework
|
||||
|
||||
if (!info.m_relativePath.empty())
|
||||
{
|
||||
const char* devAssetRoot = fileIO->GetAlias("@devassets@");
|
||||
const char* devAssetRoot = fileIO->GetAlias("@projectroot@");
|
||||
if (devAssetRoot)
|
||||
{
|
||||
AZ::Data::AssetStreamInfo streamInfo;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzFramework
|
||||
|
||||
AZ::IO::Path& gemAbsPath = gemInfo.m_absoluteSourcePaths.emplace_back(value);
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/std/containers/fixed_unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <cctype>
|
||||
|
||||
namespace AZ
|
||||
@@ -292,7 +294,7 @@ namespace AZ
|
||||
void LocalFileIO::CheckInvalidWrite([[maybe_unused]] const char* path)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* assetAliasPath = GetAlias("@products@");
|
||||
if (path && assetAliasPath)
|
||||
{
|
||||
const AZ::IO::PathView pathView(path);
|
||||
@@ -478,17 +480,15 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsAbsolutePath(path))
|
||||
if (AZ::IO::PathView(path).HasRootPath())
|
||||
{
|
||||
size_t pathLen = strlen(path);
|
||||
if (pathLen + 1 < resolvedPathSize)
|
||||
{
|
||||
azstrncpy(resolvedPath, resolvedPathSize, path, pathLen + 1);
|
||||
|
||||
//see if the absolute path uses @assets@ or @root@, if it does lowercase the relative part
|
||||
[[maybe_unused]] bool lowercasePath = LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@assets@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@root@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@projectplatformcache@"));
|
||||
//see if the absolute path matches the resolved value of @products@, if it does lowercase the relative part
|
||||
LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@products@"));
|
||||
|
||||
ToUnixSlashes(resolvedPath, resolvedPathSize);
|
||||
return true;
|
||||
@@ -499,34 +499,39 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
char rootedPathBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
constexpr AZStd::string_view productAssetAlias = "@products@";
|
||||
// Add plus one for the path separator: <alias>/<path>
|
||||
constexpr size_t MaxPathSizeWithProductAssetAlias = AZ::IO::MaxPathLength + productAssetAlias.size() + 1;
|
||||
using RootedPathString = AZStd::fixed_string<MaxPathSizeWithProductAssetAlias>;
|
||||
RootedPathString rootedPathBuffer;
|
||||
const char* rootedPath = path;
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @assets@
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @products@
|
||||
if (path[0] != '@')
|
||||
{
|
||||
if (GetAlias("@assets@"))
|
||||
if (GetAlias("@products@"))
|
||||
{
|
||||
const int rootLength = 9;// strlen("@assets@/")
|
||||
azstrncpy(rootedPathBuffer, AZ_MAX_PATH_LEN, "@assets@/", rootLength);
|
||||
size_t pathLen = strlen(path);
|
||||
size_t rootedPathBufferlength = rootLength + pathLen + 1;// +1 for null terminator
|
||||
if (rootedPathBufferlength > resolvedPathSize)
|
||||
|
||||
if (const size_t requiredSize = productAssetAlias.size() + strlen(path) + 1;
|
||||
requiredSize > rootedPathBuffer.capacity())
|
||||
{
|
||||
AZ_Assert(rootedPathBufferlength < resolvedPathSize, "Constructed path length is wrong:%s", rootedPathBuffer);//path constructed is wrong
|
||||
size_t remainingSize = resolvedPathSize - rootLength - 1;// - 1 for null terminator
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN, path, remainingSize);
|
||||
rootedPathBuffer[resolvedPathSize - 1] = '\0';
|
||||
AZ_Error("FileIO", false, "Prepending the %.*s alias to the input path results in a path longer than the"
|
||||
" AZ::IO::MaxPathLength + the alias size of %zu. The size of the potential failed path is %zu",
|
||||
AZ_STRING_ARG(productAssetAlias), rootedPathBuffer.capacity(), requiredSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN - rootLength, path, pathLen + 1);
|
||||
rootedPathBuffer = RootedPathString::format("%.*s/%s", AZ_STRING_ARG(productAssetAlias), path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertToAbsolutePath(path, rootedPathBuffer, AZ_MAX_PATH_LEN);
|
||||
if (ConvertToAbsolutePath(path, rootedPathBuffer.data(), rootedPathBuffer.capacity()))
|
||||
{
|
||||
// Recalculate the internal string length
|
||||
rootedPathBuffer.resize_no_construct(AZStd::char_traits<char>::length(rootedPathBuffer.data()));
|
||||
}
|
||||
}
|
||||
rootedPath = rootedPathBuffer;
|
||||
rootedPath = rootedPathBuffer.c_str();
|
||||
}
|
||||
|
||||
if (ResolveAliases(rootedPath, resolvedPath, resolvedPathSize))
|
||||
@@ -561,11 +566,57 @@ namespace AZ
|
||||
|
||||
const char* LocalFileIO::GetAlias(const char* key) const
|
||||
{
|
||||
const auto it = m_aliases.find(key);
|
||||
if (it != m_aliases.end())
|
||||
if (const auto it = m_aliases.find(key); it != m_aliases.end())
|
||||
{
|
||||
return it->second.c_str();
|
||||
}
|
||||
else if (const auto deprecatedIt = m_deprecatedAliases.find(key);
|
||||
deprecatedIt != m_deprecatedAliases.end())
|
||||
{
|
||||
AZ_Error("FileIO", false, R"(Alias "%s" is deprecated. Please use alias "%s" instead)",
|
||||
key, deprecatedIt->second.c_str());
|
||||
AZStd::string_view aliasValue = deprecatedIt->second;
|
||||
// Contains the list of aliases resolved so far
|
||||
// If max_size is hit, than an error is logged and nullptr is returned
|
||||
using VisitedAliasSet = AZStd::fixed_unordered_set<AZStd::string_view, 8, 8>;
|
||||
VisitedAliasSet visitedAliasSet;
|
||||
while (aliasValue.starts_with("@"))
|
||||
{
|
||||
if (visitedAliasSet.contains(aliasValue))
|
||||
{
|
||||
AZ_Error("FileIO", false, "Cycle found with for alias %.*s when trying to resolve deprecated alias %s",
|
||||
AZ_STRING_ARG(aliasValue), key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(visitedAliasSet.size() == visitedAliasSet.max_size())
|
||||
{
|
||||
AZ_Error("FileIO", false, "Unable to resolve path to deprecated alias %s within %zu steps",
|
||||
key, visitedAliasSet.max_size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add the current alias value to the visited set
|
||||
visitedAliasSet.emplace(aliasValue);
|
||||
|
||||
// Check if the alias value corresponds to another alias
|
||||
if (auto resolvedIter = m_aliases.find(aliasValue); resolvedIter != m_aliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else if (resolvedIter = m_deprecatedAliases.find(aliasValue);
|
||||
resolvedIter != m_deprecatedAliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return aliasValue.data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -574,6 +625,11 @@ namespace AZ
|
||||
m_aliases.erase(key);
|
||||
}
|
||||
|
||||
void LocalFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
m_deprecatedAliases[oldAlias] = newAlias;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> LocalFileIO::ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const
|
||||
{
|
||||
size_t longestMatch = 0;
|
||||
@@ -675,7 +731,9 @@ namespace AZ
|
||||
: string_view_pair{};
|
||||
|
||||
size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1;
|
||||
AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect");
|
||||
AZ_Assert(path != resolvedPath, "ResolveAliases does not support inplace update of the path");
|
||||
AZ_Assert(resolvedPathSize >= requiredResolvedPathSize, "Resolved path size %llu not large enough. It needs to be %zu",
|
||||
resolvedPathSize, requiredResolvedPathSize);
|
||||
// we assert above, but we also need to properly handle the case when the resolvedPath buffer size
|
||||
// is too small to copy the source into.
|
||||
if (path == resolvedPath || (resolvedPathSize < requiredResolvedPathSize))
|
||||
@@ -699,13 +757,9 @@ namespace AZ
|
||||
resolvedPath[resolvedPathLen] = '\0';
|
||||
|
||||
// If the path started with one of the "asset cache" path aliases, lowercase the path
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* rootAliasPath = GetAlias("@root@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@projectplatformcache@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@products@");
|
||||
|
||||
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
|
||||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
|
||||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
|
||||
const bool lowercasePath = projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath);
|
||||
|
||||
if (lowercasePath)
|
||||
{
|
||||
@@ -822,5 +876,10 @@ namespace AZ
|
||||
|
||||
return pathStr + "/";
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
return AZ::Utils::ConvertToAbsolutePath(path, absolutePath, maxLength);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -71,7 +73,7 @@ namespace AZ
|
||||
|
||||
bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const override;
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const;
|
||||
|
||||
|
||||
private:
|
||||
SystemFile* GetFilePointerFromHandle(HandleType fileHandle);
|
||||
|
||||
@@ -79,7 +81,6 @@ namespace AZ
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const;
|
||||
bool ResolveAliases(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const;
|
||||
bool IsAbsolutePath(const char* path) const;
|
||||
|
||||
bool LowerIfBeginsWith(char* inOutBuffer, AZ::u64 bufferLen, const char* alias) const;
|
||||
|
||||
@@ -91,6 +92,7 @@ namespace AZ
|
||||
AZStd::atomic<HandleType> m_nextHandle;
|
||||
AZStd::unordered_map<HandleType, SystemFile> m_openFiles;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_aliases;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_deprecatedAliases;
|
||||
|
||||
void CheckInvalidWrite(const char* path);
|
||||
};
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace AZ
|
||||
s_IOLog.append(m_name);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
void Append(const char* line)
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u ", m_fileOperation));
|
||||
s_IOLog.append(line);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
~LogCall()
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u End ", m_fileOperation));
|
||||
@@ -251,7 +251,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size request failed. return Error", filePath).c_str());
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
|
||||
size = response.m_size;
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size=%u. return Success", filePath, size).c_str());
|
||||
return ResultCode::Success;
|
||||
@@ -793,6 +793,12 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ClearAlias(alias=%s)", alias?alias:"nullptr").c_str());
|
||||
}
|
||||
|
||||
void NetworkFileIO::SetDeprecatedAlias([[maybe_unused]] AZStd::string_view oldAlias, [[maybe_unused]] AZStd::string_view newAlias)
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::SetDeprecatedAlias(oldAlias=%.*s, newAlias=%.*s)",
|
||||
AZ_STRING_ARG(oldAlias), AZ_STRING_ARG(newAlias)).c_str());
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> NetworkFileIO::ConvertToAlias(char* inOutBuffer, [[maybe_unused]] AZ::u64 bufferLength) const
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ConvertToAlias(inOutBuffer=%s, bufferLength=%u)", inOutBuffer?inOutBuffer:"nullptr", bufferLength).c_str());
|
||||
@@ -927,7 +933,7 @@ namespace AZ
|
||||
{
|
||||
m_cacheLookaheadPos = filePosition - CacheStartFilePosition();
|
||||
}
|
||||
|
||||
|
||||
void RemoteFileCache::SyncCheck()
|
||||
{
|
||||
#ifdef REMOTEFILEIO_SYNC_CHECK
|
||||
@@ -955,7 +961,7 @@ namespace AZ
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle);
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle).c_str());
|
||||
}
|
||||
|
||||
|
||||
if (responce.m_offset != m_filePosition)
|
||||
{
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) failed!!! m_filePosition=%u tell=%u", m_fileHandle, m_filePosition, responce.m_offset);
|
||||
@@ -1028,7 +1034,7 @@ namespace AZ
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Close(fileHandle=%u)", fileHandle).c_str());
|
||||
Result returnValue = NetworkFileIO::Close(fileHandle);
|
||||
|
||||
|
||||
if (returnValue == ResultCode::Success)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
@@ -1160,7 +1166,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Read(fileHandle=%u, buffer=OUT, size=%u, failOnFewerThanSizeBytesRead=%s, bytesRead=OUT)", fileHandle, size, failOnFewerThanSizeBytesRead ? "True" : "False").c_str());
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
|
||||
|
||||
AZ::u64 remainingBytesToRead = size;
|
||||
AZ::u64 bytesReadFromCache = 0;
|
||||
AZ::u64 remainingBytesInCache = cache.RemainingBytes();
|
||||
@@ -1263,7 +1269,7 @@ namespace AZ
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
if (cache.m_cacheLookaheadBuffer.size() && cache.RemainingBytes())
|
||||
{
|
||||
// find out where we are
|
||||
// find out where we are
|
||||
AZ::u64 seekPosition = cache.CacheFilePosition();
|
||||
|
||||
// note, seeks are predicted, and do not ask for a response.
|
||||
@@ -1361,6 +1367,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
if (m_excludedFileIO)
|
||||
{
|
||||
m_excludedFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> RemoteFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
return m_excludedFileIO ? m_excludedFileIO->ConvertToAlias(inOutBuffer, bufferLength) : strlen(inOutBuffer);
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace AZ
|
||||
Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -194,6 +195,7 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingAnd::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingOr::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
@@ -17,16 +18,38 @@ namespace AzFramework
|
||||
{
|
||||
namespace SurfaceData
|
||||
{
|
||||
namespace Constants
|
||||
{
|
||||
static const char* s_unassignedTagName = "(unassigned)";
|
||||
}
|
||||
|
||||
struct SurfaceTagWeight
|
||||
{
|
||||
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
|
||||
|
||||
AZ::Crc32 m_surfaceType;
|
||||
float m_weight; //! A Value in the range [0.0f .. 1.0f]
|
||||
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
|
||||
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
|
||||
|
||||
//! Don't call this directly. TerrainDataRequests::Reflect is doing it already.
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
struct SurfaceTagWeightComparator
|
||||
{
|
||||
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
|
||||
{
|
||||
if (!AZ::IsClose(tagWeight1.m_weight, tagWeight2.m_weight))
|
||||
{
|
||||
return tagWeight1.m_weight > tagWeight2.m_weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using OrderedSurfaceTagWeightSet = AZStd::set<SurfaceTagWeight, SurfaceTagWeightComparator>;
|
||||
} //namespace SurfaceData
|
||||
|
||||
namespace Terrain
|
||||
@@ -75,8 +98,28 @@ namespace AzFramework
|
||||
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false,
|
||||
//! otherwise *terrainExistsPtr will be set to true.
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
|
||||
|
||||
//! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore
|
||||
//! the input Z value.
|
||||
virtual void GetSurfaceWeights(
|
||||
const AZ::Vector3& inPosition,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual void GetSurfaceWeightsFromVector2(
|
||||
const AZ::Vector2& inPosition,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
virtual void GetSurfaceWeightsFromFloats(
|
||||
float x,
|
||||
float y,
|
||||
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights,
|
||||
Sampler sampleFilter = Sampler::DEFAULT,
|
||||
bool* terrainExistsPtr = nullptr) const = 0;
|
||||
|
||||
//! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats.
|
||||
//! Not available in the behavior context.
|
||||
//! Returns nullptr if the position is inside a hole or outside of the terrain boundaries.
|
||||
|
||||
@@ -29,7 +29,6 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
PUBLIC
|
||||
AZ::GridMate
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
3rdParty::lz4
|
||||
)
|
||||
|
||||
+13
-49
@@ -13,7 +13,6 @@
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/IOUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
#include <android/api-level.h>
|
||||
@@ -42,10 +41,10 @@ namespace AZ
|
||||
{
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourcePath[AZ_MAX_PATH_LEN];
|
||||
char resolvedDestPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ_MAX_PATH_LEN);
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedSourcePath[AZ::IO::MaxPathLength];
|
||||
char resolvedDestPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ::IO::MaxPathLength);
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ::IO::MaxPathLength);
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(sourceFilePath) || AZ::Android::Utils::IsApkPath(destinationFilePath))
|
||||
{
|
||||
@@ -77,18 +76,17 @@ namespace AZ
|
||||
{
|
||||
ANDROID_IO_PROFILE_SECTION_ARGS("FindFiles:%s", filePath);
|
||||
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
AZStd::string pathWithoutSlash = RemoveTrailingSlash(resolvedPath);
|
||||
bool isInAPK = AZ::Android::Utils::IsApkPath(pathWithoutSlash.c_str());
|
||||
|
||||
AZ::IO::FixedMaxPath tempBuffer;
|
||||
if (isInAPK)
|
||||
{
|
||||
AZ::IO::FixedMaxPath strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
|
||||
char tempBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
|
||||
AZ::Android::APKFileHandler::ParseDirectory(strippedPath.c_str(), [&](const char* name)
|
||||
{
|
||||
AZStd::string_view filenameView = name;
|
||||
@@ -98,10 +96,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += name;
|
||||
// if aliased, de-alias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -115,10 +112,6 @@ namespace AZ
|
||||
|
||||
if (dir != nullptr)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
|
||||
// clear the errno state so we can distinguish between errors and end of stream
|
||||
errno = 0;
|
||||
struct dirent* entry = readdir(dir);
|
||||
@@ -133,10 +126,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += entry->d_name;
|
||||
// if aliased, de-alias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -163,8 +155,8 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::CreatePath(const char* filePath)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(resolvedPath))
|
||||
{
|
||||
@@ -201,33 +193,5 @@ namespace AZ
|
||||
mkdir(pathBuffer.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
return IsDirectory(resolvedPath) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
return path && path[0] == '/';
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
if (AZ::Android::Utils::IsApkPath(path))
|
||||
{
|
||||
azstrncpy(absolutePath, maxLength, path, maxLength);
|
||||
return true;
|
||||
}
|
||||
AZ_Assert(maxLength >= AZ_MAX_PATH_LEN, "Path length is larger than AZ_MAX_PATH_LEN");
|
||||
if (!IsAbsolutePath(path))
|
||||
{
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
const char* result = realpath(path, absolutePath);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return IsAbsolutePath(absolutePath);
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
|
||||
+12
-38
@@ -10,7 +10,7 @@
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -19,11 +19,11 @@ namespace AZ
|
||||
{
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourceFilePath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(sourceFilePath, resolvedSourceFilePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedSourceFilePath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(sourceFilePath, resolvedSourceFilePath, AZ::IO::MaxPathLength);
|
||||
|
||||
char resolvedDestinationFilePath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(destinationFilePath, resolvedDestinationFilePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedDestinationFilePath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(destinationFilePath, resolvedDestinationFilePath, AZ::IO::MaxPathLength);
|
||||
|
||||
// Use standard C++ method of file copy.
|
||||
{
|
||||
@@ -45,17 +45,15 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
AZStd::string withoutSlash = RemoveTrailingSlash(resolvedPath);
|
||||
DIR* dir = opendir(withoutSlash.c_str());
|
||||
|
||||
if (dir != nullptr)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FixedMaxPath tempBuffer;
|
||||
|
||||
errno = 0;
|
||||
struct dirent* entry = readdir(dir);
|
||||
@@ -70,10 +68,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += entry->d_name;
|
||||
// if aliased, dealias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -92,8 +89,8 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::CreatePath(const char* filePath)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
// create all paths up to that directory.
|
||||
// its not an error if the path exists.
|
||||
@@ -125,28 +122,5 @@ namespace AZ
|
||||
mkdir(buf.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
return IsDirectory(resolvedPath) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
return path && path[0] == '/';
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
AZ_Assert(maxLength >= AZ_MAX_PATH_LEN, "Path length is larger than AZ_MAX_PATH_LEN");
|
||||
if (!IsAbsolutePath(path))
|
||||
{
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
const char* result = realpath(path, absolutePath);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return IsAbsolutePath(absolutePath);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
+1
-32
@@ -47,7 +47,7 @@ namespace AZ
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// because the absolute path might actually be SHORTER than the alias ("D:/o3de" -> "@engroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
do
|
||||
@@ -133,36 +133,5 @@ namespace AZ
|
||||
|
||||
return SystemFile::CreateDir(buf.c_str()) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
char* result = _fullpath(absolutePath, path, maxLength);
|
||||
size_t len = ::strlen(absolutePath);
|
||||
if (len > 0)
|
||||
{
|
||||
// strip trailing slash
|
||||
if (absolutePath[len - 1] == '/' || absolutePath[len - 1] == '\\')
|
||||
{
|
||||
absolutePath[len - 1] = 0;
|
||||
}
|
||||
|
||||
// For some reason, at least on windows, _fullpath returns a lowercase drive letter even though other systems like Qt, use upper case.
|
||||
if (len > 2)
|
||||
{
|
||||
if (absolutePath[1] == ':')
|
||||
{
|
||||
absolutePath[0] = (char)toupper(absolutePath[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
char drive[16] = { 0 };
|
||||
_splitpath_s(path, drive, 16, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
return strlen(drive) > 0;
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
|
||||
+15
-17
@@ -7,26 +7,24 @@
|
||||
*/
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::IO
|
||||
{
|
||||
namespace IO
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
AZ::IO::FixedMaxPath resolvedSourcePath;
|
||||
ResolvePath(resolvedSourcePath, sourceFilePath);
|
||||
AZ::IO::FixedMaxPath resolvedDestPath;
|
||||
ResolvePath(resolvedDestPath, destinationFilePath);
|
||||
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourcePath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedDestPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ_MAX_PATH_LEN);
|
||||
AZStd::fixed_wstring<AZ::IO::MaxPathLength> resolvedSourcePathW;
|
||||
AZStd::fixed_wstring<AZ::IO::MaxPathLength> resolvedDestPathW;
|
||||
AZStd::to_wstring(resolvedSourcePathW, resolvedSourcePath.Native());
|
||||
AZStd::to_wstring(resolvedDestPathW, resolvedDestPath.Native());
|
||||
|
||||
if (::CopyFileA(resolvedSourcePath, resolvedDestPath, false) == 0)
|
||||
{
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
return ResultCode::Success;
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
return ::CopyFileW(resolvedSourcePathW.c_str(), resolvedDestPathW.c_str(), false) != 0 ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
}//namespace AZ::IO
|
||||
|
||||
@@ -26,7 +26,7 @@ protected:
|
||||
}
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", m_tempDirectory.GetDirectory());
|
||||
fileIoBase->SetAlias("@products@", m_tempDirectory.GetDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace UnitTest
|
||||
|
||||
m_application->Start({});
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
}
|
||||
@@ -262,7 +262,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withSubfolders.c_str()));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", testArchivePath_withSubfolders.c_str()));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", testArchivePath_withSubfolders.c_str()));
|
||||
|
||||
EXPECT_TRUE(archive->IsFileExist(fileInArchiveFile));
|
||||
}
|
||||
@@ -353,7 +353,7 @@ namespace UnitTest
|
||||
// and be able to IMMEDIATELY
|
||||
// * read the file in the subfolder
|
||||
// * enumerate the folders (including that subfolder) even though they are 'virtual', not real folders on physical media
|
||||
// * all of the above even though the mount point for the archive is @assets@ wheras the physical pack lives in @usercache@
|
||||
// * all of the above even though the mount point for the archive is @products@ wheras the physical pack lives in @usercache@
|
||||
// finally, we're going to repeat the above test but with files mounted with subfolders
|
||||
// so for example, the pack will contain levelinfo.xml at the root of it
|
||||
// but it will be mounted at a subfolder (levels/mylevel).
|
||||
@@ -388,7 +388,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withSubfolders));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", testArchivePath_withSubfolders));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", testArchivePath_withSubfolders));
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(archive->IsFileExist("levels\\mylevel\\levelinfo.xml"));
|
||||
EXPECT_TRUE(archive->IsFileExist("levels//mylevel//levelinfo.xml"));
|
||||
@@ -484,7 +484,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withMountPoint));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@\\uniquename\\mylevel2", testArchivePath_withMountPoint));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@\\uniquename\\mylevel2", testArchivePath_withMountPoint));
|
||||
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(archive->IsFileExist("uniquename\\mylevel2\\levelinfo.xml"));
|
||||
@@ -543,7 +543,7 @@ namespace UnitTest
|
||||
archive->ClosePack(testArchivePath_withMountPoint);
|
||||
|
||||
// --- test to make sure that when you iterate only the first component is found, so bury it deep and ask for the root
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@\\uniquename\\mylevel2\\mylevel3\\mylevel4", testArchivePath_withMountPoint));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@\\uniquename\\mylevel2\\mylevel3\\mylevel4", testArchivePath_withMountPoint));
|
||||
|
||||
found_mylevel_folder = false;
|
||||
handle = archive->FindFirst("uniquename\\*");
|
||||
@@ -574,9 +574,9 @@ namespace UnitTest
|
||||
found_mylevel_folder = false;
|
||||
|
||||
// now make sure no red herrings appear
|
||||
// for example, if a file is mounted at "@assets@\\uniquename\\mylevel2\\mylevel3\\mylevel4"
|
||||
// and the file "@assets@\\somethingelse" is requested it should not be found
|
||||
// in addition if the file "@assets@\\uniquename\\mylevel3" is requested it should not be found
|
||||
// for example, if a file is mounted at "@products@\\uniquename\\mylevel2\\mylevel3\\mylevel4"
|
||||
// and the file "@products@\\somethingelse" is requested it should not be found
|
||||
// in addition if the file "@products@\\uniquename\\mylevel3" is requested it should not be found
|
||||
handle = archive->FindFirst("somethingelse\\*");
|
||||
EXPECT_FALSE(static_cast<bool>(handle));
|
||||
|
||||
@@ -610,7 +610,7 @@ namespace UnitTest
|
||||
cpfio.Remove(genericArchiveFileName);
|
||||
|
||||
// create the asset alias directory
|
||||
cpfio.CreatePath("@assets@");
|
||||
cpfio.CreatePath("@products@");
|
||||
|
||||
// create generic file
|
||||
|
||||
@@ -635,11 +635,11 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(genericArchiveFileName));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", genericArchiveFileName));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", genericArchiveFileName));
|
||||
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(cpfio.Exists("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@assets@/testfile.xml")); // this should be hte same file
|
||||
EXPECT_TRUE(cpfio.Exists("@products@/testfile.xml")); // this should be hte same file
|
||||
EXPECT_TRUE(!cpfio.Exists("@log@/testfile.xml"));
|
||||
EXPECT_TRUE(!cpfio.Exists("@usercache@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
@@ -685,9 +685,9 @@ namespace UnitTest
|
||||
EXPECT_EQ(ResultCode::Success, cpfio.Close(normalFileHandle));
|
||||
|
||||
EXPECT_TRUE(!cpfio.IsDirectory("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsDirectory("@assets@"));
|
||||
EXPECT_TRUE(cpfio.IsDirectory("@products@"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("@assets@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("@products@/testfile.xml"));
|
||||
EXPECT_TRUE(!cpfio.IsReadOnly("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
|
||||
|
||||
@@ -714,10 +714,10 @@ namespace UnitTest
|
||||
|
||||
// find files test.
|
||||
AZ::IO::FixedMaxPath resolvedTestFilePath;
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedTestFilePath, AZ::IO::PathView("@assets@/testfile.xml")));
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedTestFilePath, AZ::IO::PathView("@products@/testfile.xml")));
|
||||
bool foundIt = false;
|
||||
// note that this file exists only in the archive.
|
||||
cpfio.FindFiles("@assets@", "*.xml", [&foundIt, &cpfio, &resolvedTestFilePath](const char* foundName)
|
||||
cpfio.FindFiles("@products@", "*.xml", [&foundIt, &cpfio, &resolvedTestFilePath](const char* foundName)
|
||||
{
|
||||
AZ::IO::FixedMaxPath resolvedFoundPath;
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedFoundPath, AZ::IO::PathView(foundName)));
|
||||
@@ -734,10 +734,10 @@ namespace UnitTest
|
||||
|
||||
|
||||
// The following test is disabled because it will trigger an AZ_ERROR which will affect the outcome of this entire test
|
||||
// EXPECT_NE(ResultCode::Success, cpfio.Remove("@assets@/testfile.xml")); // may not delete archive files
|
||||
// EXPECT_NE(ResultCode::Success, cpfio.Remove("@products@/testfile.xml")); // may not delete archive files
|
||||
|
||||
// make sure it works with and without alias:
|
||||
EXPECT_TRUE(cpfio.Exists("@assets@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@products@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("testfile.xml"));
|
||||
|
||||
EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
@@ -788,22 +788,22 @@ namespace UnitTest
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
// change its actual location:
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@assets@/foundit.dat"));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous location!
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/notfoundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat"));
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
// try sub-folders
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@/mystuff", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@assets@/mystuff/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_TRUE(archive->OpenPack("@products@/mystuff", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/mystuff/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/mystuff/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/notfoundit.dat")); // non-existent file
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ namespace UnitTest
|
||||
AZ::IO::FileIOBase* ioBase = AZ::IO::FileIOBase::GetInstance();
|
||||
ASSERT_NE(nullptr, ioBase);
|
||||
|
||||
const char* assetsPath = ioBase->GetAlias("@assets@");
|
||||
const char* assetsPath = ioBase->GetAlias("@products@");
|
||||
ASSERT_NE(nullptr, assetsPath);
|
||||
|
||||
auto stringToAdd = AZ::IO::Path(assetsPath) / "textures" / "test.dds";
|
||||
@@ -872,7 +872,7 @@ namespace UnitTest
|
||||
// it normalizes the string, so the slashes flip and everything is lowercased.
|
||||
AZ::IO::FixedMaxPath resolvedAddedPath;
|
||||
AZ::IO::FixedMaxPath resolvedResourcePath;
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedAddedPath, "@assets@/textures/test.dds"));
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedAddedPath, "@products@/textures/test.dds"));
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedResourcePath, reslist->GetFirst()));
|
||||
EXPECT_EQ(resolvedAddedPath, resolvedResourcePath);
|
||||
reslist->Clear();
|
||||
|
||||
@@ -802,6 +802,51 @@ namespace UnitTest
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(AliasTest, GetAlias_LogsError_WhenAccessingDeprecatedAlias_Succeeds)
|
||||
{
|
||||
AZ::IO::LocalFileIO local;
|
||||
|
||||
AZ::IO::FixedMaxPathString aliasFolder;
|
||||
EXPECT_TRUE(local.ConvertToAbsolutePath("/temp", aliasFolder.data(), aliasFolder.capacity()));
|
||||
aliasFolder.resize_no_construct(AZStd::char_traits<char>::length(aliasFolder.data()));
|
||||
|
||||
local.SetAlias("@test@", aliasFolder.c_str());
|
||||
local.SetDeprecatedAlias("@deprecated@", "@test@");
|
||||
local.SetDeprecatedAlias("@deprecatednonexistent@", "@nonexistent@");
|
||||
local.SetDeprecatedAlias("@deprecatedsecond@", "@deprecated@");
|
||||
local.SetDeprecatedAlias("@deprecatednonaliaspath@", aliasFolder);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
const char* testAlias = local.GetAlias("@test@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(0);
|
||||
|
||||
// Validate that accessing Deprecated Alias results in AZ_Error
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecated@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatednonexistent@");
|
||||
EXPECT_EQ(nullptr, testAlias);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatedsecond@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatednonaliaspath@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
class SmartMoveTests
|
||||
: public FolderFixture
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace UnitTest
|
||||
|
||||
const char DummyFile[] = "dummy.txt";
|
||||
const char AnotherDummyFile[] = "Foo/Dummy.txt";
|
||||
|
||||
|
||||
const char DummyPattern[] = R"(^(.+)_([a-z]+)\..+$)";
|
||||
const char MatchingPatternFile[] = "Foo/dummy_abc.txt";
|
||||
const char NonMatchingPatternFile[] = "Foo/dummy_a8c.txt";
|
||||
@@ -75,7 +75,7 @@ namespace UnitTest
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsFixture::SetUp();
|
||||
@@ -89,7 +89,7 @@ namespace UnitTest
|
||||
const char* testAssetRoot = m_tempDirectory.GetDirectory();
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace UnitTest
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr);
|
||||
AZ::IO::FileIOBase::SetInstance(m_data->m_localFileIO.get());
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", testAssetRoot);
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", testAssetRoot);
|
||||
|
||||
m_data->m_excludeFileQueryManager = AZStd::make_unique<FileTagQueryManagerTest>(FileTagType::Exclude);
|
||||
m_data->m_includeFileQueryManager = AZStd::make_unique<FileTagQueryManagerTest>(FileTagType::Include);
|
||||
@@ -114,7 +114,7 @@ namespace UnitTest
|
||||
|
||||
AZStd::vector<AZStd::string> includedWildcardTags = { DummyFileTags[DummyFileTagIndex::GIdx] };
|
||||
EXPECT_TRUE(m_data->m_fileTagManager.AddFilePatternTags(DummyWildcard, FilePatternType::Wildcard, FileTagType::Include, includedWildcardTags).IsSuccess());
|
||||
|
||||
|
||||
AzFramework::StringFunc::Path::Join(testAssetRoot, AZStd::string::format("%s.%s", ExcludeFile, FileTagAsset::Extension()).c_str(), m_data->m_excludeFile);
|
||||
|
||||
AzFramework::StringFunc::Path::Join(testAssetRoot, AZStd::string::format("%s.%s", IncludeFile, FileTagAsset::Extension()).c_str(), m_data->m_includeFile);
|
||||
@@ -184,7 +184,7 @@ namespace UnitTest
|
||||
TEST_F(FileTagTest, FileTags_QueryByAbsoluteFilePath_Valid)
|
||||
{
|
||||
AZStd::string absoluteDummyFilePath = DummyFile;
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@assets@", absoluteDummyFilePath.c_str(), absoluteDummyFilePath));
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@products@", absoluteDummyFilePath.c_str(), absoluteDummyFilePath));
|
||||
|
||||
AZStd::set<AZStd::string> tags = m_data->m_excludeFileQueryManager->GetTags(absoluteDummyFilePath);
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace UnitTest
|
||||
ASSERT_EQ(tags.size(), 0);
|
||||
|
||||
AZStd::string absoluteAnotherDummyFilePath = AnotherDummyFile;
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@assets@", absoluteAnotherDummyFilePath.c_str(), absoluteAnotherDummyFilePath));
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@products@", absoluteAnotherDummyFilePath.c_str(), absoluteAnotherDummyFilePath));
|
||||
|
||||
tags = m_data->m_includeFileQueryManager->GetTags(absoluteAnotherDummyFilePath);
|
||||
ASSERT_EQ(tags.size(), 2);
|
||||
@@ -213,7 +213,7 @@ namespace UnitTest
|
||||
|
||||
// Set the customized alias
|
||||
AZStd::string customizedAliasFilePath;
|
||||
const char* assetsAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@");
|
||||
const char* assetsAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@");
|
||||
AzFramework::StringFunc::AssetDatabasePath::Join(assetsAlias, "foo", customizedAliasFilePath);
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@customizedalias@", customizedAliasFilePath.c_str());
|
||||
|
||||
@@ -305,7 +305,7 @@ namespace UnitTest
|
||||
|
||||
m_data->m_excludeFileQueryManager->ClearData();
|
||||
EXPECT_TRUE(m_data->m_excludeFileQueryManager->Load(m_data->m_excludeFile));
|
||||
|
||||
|
||||
AZStd::set<AZStd::string> outputTags = m_data->m_excludeFileQueryManager->GetTags(MatchingWildcardFile);
|
||||
|
||||
EXPECT_EQ(outputTags.size(), 2);
|
||||
|
||||
@@ -6,81 +6,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzTest/Utils.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
class FileIOBaseRAII
|
||||
{
|
||||
public:
|
||||
FileIOBaseRAII(AZ::IO::FileIOBase& fileIO)
|
||||
: m_prevFileIO(AZ::IO::FileIOBase::GetInstance())
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(&fileIO);
|
||||
}
|
||||
|
||||
~FileIOBaseRAII()
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(m_prevFileIO);
|
||||
}
|
||||
private:
|
||||
AZ::IO::FileIOBase* m_prevFileIO;
|
||||
};
|
||||
|
||||
class GenAppDescriptors
|
||||
: public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
|
||||
void run()
|
||||
{
|
||||
struct Config
|
||||
{
|
||||
const char* platformName;
|
||||
const char* configName;
|
||||
const char* libSuffix;
|
||||
};
|
||||
|
||||
ComponentApplication app;
|
||||
|
||||
SerializeContext serializeContext;
|
||||
AZ::ComponentApplication::Descriptor::Reflect(&serializeContext, &app);
|
||||
AZ::Entity::Reflect(&serializeContext);
|
||||
DynamicModuleDescriptor::Reflect(&serializeContext);
|
||||
|
||||
AZ::Entity dummySystemEntity(AZ::SystemEntityId, "SystemEntity");
|
||||
|
||||
const Config config = {"Platform", "Config", "libSuffix"};
|
||||
|
||||
AZ::ComponentApplication::Descriptor descriptor;
|
||||
|
||||
if (config.libSuffix && config.libSuffix[0])
|
||||
{
|
||||
FakePopulateModules(descriptor, config.libSuffix);
|
||||
}
|
||||
|
||||
const AZStd::string filename = AZStd::string::format("LYConfig_%s%s.xml", config.platformName, config.configName);
|
||||
|
||||
IO::FileIOStream stream(filename.c_str(), IO::OpenMode::ModeWrite);
|
||||
ObjectStream* objStream = ObjectStream::Create(&stream, serializeContext, ObjectStream::ST_XML);
|
||||
bool descWriteOk = objStream->WriteClass(&descriptor);
|
||||
(void)descWriteOk;
|
||||
AZ_Warning("ComponentApplication", descWriteOk, "Failed to write memory descriptor to application descriptor file %s!", filename.c_str());
|
||||
bool entityWriteOk = objStream->WriteClass(&dummySystemEntity);
|
||||
(void)entityWriteOk;
|
||||
AZ_Warning("ComponentApplication", entityWriteOk, "Failed to write system entity to application descriptor file %s!", filename.c_str());
|
||||
bool flushOk = objStream->Finalize();
|
||||
(void)flushOk;
|
||||
AZ_Warning("ComponentApplication", flushOk, "Failed finalizing application descriptor file %s!", filename.c_str());
|
||||
|
||||
}
|
||||
|
||||
void FakePopulateModules(AZ::ComponentApplication::Descriptor& desc, const char* libSuffix)
|
||||
{
|
||||
static const char* modules[] =
|
||||
@@ -100,10 +38,44 @@ namespace UnitTest
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(GenAppDescriptors, Test)
|
||||
TEST_F(GenAppDescriptors, WriteDescriptor_ToXML_Succeeds)
|
||||
{
|
||||
AZ::IO::LocalFileIO fileIO;
|
||||
FileIOBaseRAII restoreFileIOScope(fileIO);
|
||||
run();
|
||||
struct Config
|
||||
{
|
||||
const char* platformName;
|
||||
const char* configName;
|
||||
const char* libSuffix;
|
||||
};
|
||||
|
||||
AzFramework::Application app;
|
||||
|
||||
AZ::SerializeContext serializeContext;
|
||||
AZ::ComponentApplication::Descriptor::Reflect(&serializeContext, &app);
|
||||
AZ::Entity::Reflect(&serializeContext);
|
||||
AZ::DynamicModuleDescriptor::Reflect(&serializeContext);
|
||||
|
||||
AZ::Entity dummySystemEntity(AZ::SystemEntityId, "SystemEntity");
|
||||
|
||||
const Config config = {"Platform", "Config", "libSuffix"};
|
||||
|
||||
AZ::ComponentApplication::Descriptor descriptor;
|
||||
|
||||
if (config.libSuffix && config.libSuffix[0])
|
||||
{
|
||||
FakePopulateModules(descriptor, config.libSuffix);
|
||||
}
|
||||
|
||||
AZ::Test::ScopedAutoTempDirectory tempDirectory;
|
||||
const auto filename = AZ::IO::Path(tempDirectory.GetDirectory()) /
|
||||
AZStd::string::format("LYConfig_%s%s.xml", config.platformName, config.configName);
|
||||
|
||||
AZ::IO::FileIOStream stream(filename.c_str(), AZ::IO::OpenMode::ModeWrite);
|
||||
auto objStream = AZ::ObjectStream::Create(&stream, serializeContext, AZ::ObjectStream::ST_XML);
|
||||
const bool descWriteOk = objStream->WriteClass(&descriptor);
|
||||
EXPECT_TRUE(descWriteOk) << "Failed to write memory descriptor to application descriptor file " << filename.c_str() << "!";
|
||||
const bool entityWriteOk = objStream->WriteClass(&dummySystemEntity);
|
||||
EXPECT_TRUE(entityWriteOk) << "Failed to write system entity to application descriptor file " << filename.c_str() << "!";
|
||||
const bool flushOk = objStream->Finalize();
|
||||
EXPECT_TRUE(flushOk) << "Failed finalizing application descriptor file " << filename.c_str() << "!";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,20 +28,22 @@ namespace AzGameFramework
|
||||
// can read from the FileIOBase instance if available
|
||||
m_settingsRegistry->SetUseFileIO(true);
|
||||
|
||||
// Attempt to mount the engine pak from the Executable Directory
|
||||
// at the Assets alias, otherwise to attempting to mount the engine pak
|
||||
// from the Cache folder
|
||||
AZ::IO::FixedMaxPath enginePakPath = AZ::Utils::GetExecutableDirectory();
|
||||
enginePakPath /= "engine.pak";
|
||||
if (!m_archive->OpenPack("@assets@", enginePakPath.Native()))
|
||||
// Attempt to mount the engine pak to the project product asset alias
|
||||
// Search Order:
|
||||
// - Project Cache Root Directory
|
||||
// - Executable Directory
|
||||
bool enginePakOpened{};
|
||||
AZ::IO::FixedMaxPath enginePakPath;
|
||||
if (m_settingsRegistry->Get(enginePakPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
enginePakPath.clear();
|
||||
if (m_settingsRegistry->Get(enginePakPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
// fall back to checking Project Cache Root.
|
||||
enginePakPath /= "engine.pak";
|
||||
m_archive->OpenPack("@assets@", enginePakPath.Native());
|
||||
}
|
||||
// fall back to checking Project Cache Root.
|
||||
enginePakPath /= "engine.pak";
|
||||
enginePakOpened = m_archive->OpenPack("@products@", enginePakPath.Native());
|
||||
}
|
||||
if (!enginePakOpened)
|
||||
{
|
||||
enginePakPath = AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / "engine.pak";
|
||||
m_archive->OpenPack("@products@", enginePakPath.Native());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,25 @@ namespace {{ xml.attrib['Name'] }}
|
||||
{
|
||||
switch (aznumeric_cast<int32_t>(packetHeader.GetPacketType()))
|
||||
{
|
||||
{% set packet_ns = namespace(handshake=false) %}
|
||||
{% for Packet in xml.iter('Packet') %}
|
||||
{% if ('HandshakePacket' in Packet.attrib) and (Packet.attrib['HandshakePacket']|booleanTrue == true) %}
|
||||
{% set packet_ns.handshake = True %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for Packet in xml.iter('Packet') %}
|
||||
case aznumeric_cast<int32_t>({{ Packet.attrib['Name'] }}::Type):
|
||||
{
|
||||
AZLOG(Debug_DispatchPackets, "Received packet %s", "{{ Packet.attrib['Name'] }}");
|
||||
{% if ('HandshakePacket' not in Packet.attrib) or (Packet.attrib['HandshakePacket'] == 'false') %}
|
||||
if (!handler.IsHandshakeComplete())
|
||||
{% if packet_ns.handshake %}
|
||||
{% if ('HandshakePacket' not in Packet.attrib) or (Packet.attrib['HandshakePacket'] == 'false') %}
|
||||
if (!handler.IsHandshakeComplete(connection))
|
||||
{
|
||||
return AzNetworking::PacketDispatchResult::Skipped;
|
||||
}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ Packet.attrib['Name'] }} packet;
|
||||
if (!serializer.Serialize(packet, "Packet"))
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace AzNetworking
|
||||
if (AZ::IO::FileIOBase::GetInstance() != nullptr)
|
||||
{
|
||||
char buffer[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@assets@/", buffer, sizeof(buffer));
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@products@/", buffer, sizeof(buffer));
|
||||
assetDir = AZStd::string(buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzCore
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
3rdParty::OpenSSL
|
||||
PUBLIC
|
||||
|
||||
@@ -47,14 +47,6 @@ namespace AzToolsFramework
|
||||
|
||||
//! Retrieve the absolute path for the Asset Database Location
|
||||
virtual bool GetAbsoluteAssetDatabaseLocation(AZStd::string& /*result*/) { return false; }
|
||||
|
||||
//! Retrieve the absolute folder path to the current game's source assets (the ones that go into source control)
|
||||
//! This may include the current mod path, if a mod is being edited by the editor
|
||||
virtual const char* GetAbsoluteDevGameFolderPath() = 0;
|
||||
|
||||
//! Retrieve the absolute folder path to the current developer root ('dev'), which contains source artifacts
|
||||
//! and is generally checked into source control.
|
||||
virtual const char* GetAbsoluteDevRootFolderPath() = 0;
|
||||
|
||||
/// Convert a full source path like "c:\\dev\\gamename\\blah\\test.tga" into a relative product path.
|
||||
/// asset paths never mention their alias and are relative to the asset cache root
|
||||
|
||||
@@ -764,12 +764,6 @@ namespace AzToolsFramework
|
||||
//! Spawn asset browser for the appropriate asset types.
|
||||
virtual void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) = 0;
|
||||
|
||||
/// Allow interception of selection / left-mouse clicks in ObjectMode, for customizing selection behavior.
|
||||
virtual void HandleObjectModeSelection(const AZ::Vector2& /*point*/, int /*flags*/, bool& /*handled*/) {}
|
||||
|
||||
/// Allow interception of cursor, for customizing selection behavior.
|
||||
virtual void UpdateObjectModeCursor(AZ::u32& /*cursorId*/, AZStd::string& /*cursorStr*/) {}
|
||||
|
||||
/// Creates editor-side representation of an underlying entity.
|
||||
virtual void CreateEditorRepresentation(AZ::Entity* /*entity*/) { }
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <AzToolsFramework/ToolsComponents/EditorAssetMimeDataContainer.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeSystemComponent.h>
|
||||
@@ -251,6 +252,7 @@ namespace AzToolsFramework
|
||||
azrtti_typeid<EditorEntityContextComponent>(),
|
||||
azrtti_typeid<Components::EditorEntityUiSystemComponent>(),
|
||||
azrtti_typeid<FocusModeSystemComponent>(),
|
||||
azrtti_typeid<ContainerEntitySystemComponent>(),
|
||||
azrtti_typeid<SliceMetadataEntityContextComponent>(),
|
||||
azrtti_typeid<Prefab::PrefabSystemComponent>(),
|
||||
azrtti_typeid<EditorEntityFixupComponent>(),
|
||||
|
||||
@@ -354,26 +354,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
const char* AssetSystemComponent::GetAbsoluteDevGameFolderPath()
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (fileIO)
|
||||
{
|
||||
return fileIO->GetAlias("@devassets@");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* AssetSystemComponent::GetAbsoluteDevRootFolderPath()
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (fileIO)
|
||||
{
|
||||
return fileIO->GetAlias("@devroot@");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void AssetSystemComponent::OnSystemTick()
|
||||
{
|
||||
AssetSystemBus::ExecuteQueuedEvents();
|
||||
|
||||
@@ -56,8 +56,6 @@ namespace AzToolsFramework
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzToolsFramework::AssetSystemRequestBus::Handler overrides
|
||||
bool GetAbsoluteAssetDatabaseLocation(AZStd::string& result) override;
|
||||
const char* GetAbsoluteDevGameFolderPath() override;
|
||||
const char* GetAbsoluteDevRootFolderPath() override;
|
||||
bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& outputPath) override;
|
||||
bool GenerateRelativeSourcePath(
|
||||
const AZStd::string& sourcePath, AZStd::string& outputPath, AZStd::string& watchFolder) override;
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace AzToolsFramework
|
||||
AssetEditorWidgetUserSettings::AssetEditorWidgetUserSettings()
|
||||
{
|
||||
char assetRoot[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", assetRoot, AZ_MAX_PATH_LEN);
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@projectroot@", assetRoot, AZ_MAX_PATH_LEN);
|
||||
|
||||
m_lastSavePath = assetRoot;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzToolsFramework/AssetBundle/AssetBundleComponent.h>
|
||||
#include <AzToolsFramework/Component/EditorComponentAPIComponent.h>
|
||||
#include <AzToolsFramework/Component/EditorLevelComponentAPIComponent.h>
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityFixupComponent.h>
|
||||
@@ -70,6 +71,7 @@ namespace AzToolsFramework
|
||||
Components::EditorSelectionAccentSystemComponent::CreateDescriptor(),
|
||||
EditorEntityContextComponent::CreateDescriptor(),
|
||||
EditorEntityFixupComponent::CreateDescriptor(),
|
||||
ContainerEntitySystemComponent::CreateDescriptor(),
|
||||
FocusModeSystemComponent::CreateDescriptor(),
|
||||
SliceMetadataEntityContextComponent::CreateDescriptor(),
|
||||
SliceRequestComponent::CreateDescriptor(),
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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/Interface/Interface.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
//! Outcome object that returns an error message in case of failure to allow caller to handle internal errors.
|
||||
using ContainerEntityOperationResult = AZ::Outcome<void, AZStd::string>;
|
||||
|
||||
//! ContainerEntityInterface
|
||||
//! An entity registered as Container is just like a regular entity when open. If its state is changed
|
||||
//! to closed, all descendants of the entity will be treated as part of the entity itself. Selecting any
|
||||
//! descendant will result in the container being selected, and descendants will be hidden until the
|
||||
//! container is opened.
|
||||
class ContainerEntityInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ContainerEntityInterface, "{0A877C3A-726C-4FD2-BAFE-A2B9F1DE78E4}");
|
||||
|
||||
//! Registers the entity as a container. The container will be closed by default.
|
||||
//! @param entityId The entityId that will be registered as a container.
|
||||
virtual ContainerEntityOperationResult RegisterEntityAsContainer(AZ::EntityId entityId) = 0;
|
||||
|
||||
//! Unregisters the entity as a container.
|
||||
//! The system will retain the closed state in case the entity is registered again later, but
|
||||
//! if queried the entity will no longer behave as a container.
|
||||
//! @param entityId The entityId that will be unregistered as a container.
|
||||
virtual ContainerEntityOperationResult UnregisterEntityAsContainer(AZ::EntityId entityId) = 0;
|
||||
|
||||
//! Returns whether the entity id provided is registered as a container.
|
||||
virtual bool IsContainer(AZ::EntityId entityId) const = 0;
|
||||
|
||||
//! Sets the open state of the container entity provided.
|
||||
//! @param entityId The entityId whose open state will be set.
|
||||
//! @param open True if the container should be opened, false if it should be closed.
|
||||
//! @return An error message if the operation was invalid, success otherwise.
|
||||
virtual ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) = 0;
|
||||
|
||||
//! If the entity id provided is registered as a container, it returns whether it's open.
|
||||
//! @note the default value for non-containers is true, so this function can be called without
|
||||
//! verifying whether the entityId is registered as a container beforehand, since the container's
|
||||
//! open behavior is exactly the same as the one of a regular entity.
|
||||
//! @return False if the entityId is registered as a container, and its state is closed. True otherwise.
|
||||
virtual bool IsContainerOpen(AZ::EntityId entityId) const = 0;
|
||||
|
||||
//! Detects if one of the ancestors of entityId is a closed container entity.
|
||||
//! @return The highest closed entity container id if any, or entityId otherwise.
|
||||
virtual AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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/Component/EntityId.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
//! Used to notify changes of state for Container Entities.
|
||||
class ContainerEntityNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
using BusIdType = AzFramework::EntityContextId;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Triggered when a container entity status changes.
|
||||
//! @param entityId The entity whose status has changed.
|
||||
//! @param open The open state the container was changed to.
|
||||
virtual void OnContainerEntityStatusChanged([[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] bool open) {}
|
||||
|
||||
protected:
|
||||
~ContainerEntityNotifications() = default;
|
||||
};
|
||||
|
||||
using ContainerEntityNotificationBus = AZ::EBus<ContainerEntityNotifications>;
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user