Merge branch 'upstream/development' into LYN-7655_MultiplayerEditorToEditorServerConnectionReverse
This commit is contained in:
@@ -8,11 +8,14 @@
|
||||
## Deploy CDK Applications
|
||||
1. Go to the AWS IAM console and create an IAM role called o3de-automation-tests which adds your own account as as a trusted entity and uses the "AdministratorAccess" permissions policy.
|
||||
2. Copy {engine_root}\scripts\build\Platform\Windows\deploy_cdk_applications.cmd to your engine root folder.
|
||||
3. Open a new Command Prompt window at the engine root and set the following environment variables:
|
||||
3. Open a new Command Prompt window at the engine root and set the following environment variables:
|
||||
```
|
||||
Set O3DE_AWS_PROJECT_NAME=AWSAUTO
|
||||
Set O3DE_AWS_DEPLOY_REGION=us-east-1
|
||||
Set O3DE_AWS_DEPLOY_ACCOUNT={your_aws_account_id}
|
||||
Set ASSUME_ROLE_ARN=arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests
|
||||
Set COMMIT_ID=HEAD
|
||||
```
|
||||
4. In the same Command Prompt window, Deploy the CDK applications for AWS gems by running deploy_cdk_applications.cmd.
|
||||
|
||||
## Run Automation Tests
|
||||
|
||||
@@ -253,73 +253,3 @@ class TestAtomEditorComponentsMain(object):
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_generic'])
|
||||
@pytest.mark.system
|
||||
class TestMaterialEditorBasicTests(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project):
|
||||
def delete_files():
|
||||
file_system.delete(
|
||||
[
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material.material"),
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material_1.material"),
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material_2.material"),
|
||||
],
|
||||
True,
|
||||
True,
|
||||
)
|
||||
# Cleanup our newly created materials
|
||||
delete_files()
|
||||
|
||||
def teardown():
|
||||
# Cleanup our newly created materials
|
||||
delete_files()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
|
||||
@pytest.mark.test_case_id("C34448113") # Creating a New Asset.
|
||||
@pytest.mark.test_case_id("C34448114") # Opening an Existing Asset.
|
||||
@pytest.mark.test_case_id("C34448115") # Closing Selected Material.
|
||||
@pytest.mark.test_case_id("C34448116") # Closing All Materials.
|
||||
@pytest.mark.test_case_id("C34448117") # Closing all but Selected Material.
|
||||
@pytest.mark.test_case_id("C34448118") # Saving Material.
|
||||
@pytest.mark.test_case_id("C34448119") # Saving as a New Material.
|
||||
@pytest.mark.test_case_id("C34448120") # Saving as a Child Material.
|
||||
@pytest.mark.test_case_id("C34448121") # Saving all Open Materials.
|
||||
def test_MaterialEditorBasicTests(
|
||||
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name):
|
||||
|
||||
expected_lines = [
|
||||
"Material opened: True",
|
||||
"Test asset doesn't exist initially: True",
|
||||
"New asset created: True",
|
||||
"New Material opened: True",
|
||||
"Material closed: True",
|
||||
"All documents closed: True",
|
||||
"Close All Except Selected worked as expected: True",
|
||||
"Actual Document saved with changes: True",
|
||||
"Document saved as copy is saved with changes: True",
|
||||
"Document saved as child is saved with changes: True",
|
||||
"Save All worked as expected: True",
|
||||
]
|
||||
unexpected_lines = [
|
||||
# "Trace::Assert",
|
||||
# "Trace::Error",
|
||||
"Traceback (most recent call last):"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
TEST_DIRECTORY,
|
||||
generic_launcher,
|
||||
"hydra_AtomMaterialEditor_BasicTests.py",
|
||||
run_python="--runpython",
|
||||
timeout=120,
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
halt_on_unexpected=True,
|
||||
null_renderer=True,
|
||||
log_file_name="MaterialEditor.log",
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ class TestAllComponentsIndepthTests(object):
|
||||
|
||||
level_creation_expected_lines = [
|
||||
"Viewport is set to the expected size: True",
|
||||
"Basic level created"
|
||||
"Exited game mode"
|
||||
]
|
||||
unexpected_lines = [
|
||||
"Trace::Assert",
|
||||
@@ -189,8 +189,8 @@ class TestPerformanceBenchmarkSuite(object):
|
||||
"Benchmark metadata captured.",
|
||||
"Pass timestamps captured.",
|
||||
"CPU frame time captured.",
|
||||
"Capturing complete.",
|
||||
"Captured data successfully."
|
||||
"Captured data successfully.",
|
||||
"Exited game mode"
|
||||
]
|
||||
|
||||
unexpected_lines = [
|
||||
|
||||
@@ -14,10 +14,6 @@ import editor_python_test_tools.hydra_test_utils as hydra
|
||||
logger = logging.getLogger(__name__)
|
||||
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("level", ["auto_test"])
|
||||
class TestAtomEditorComponentsSandbox(object):
|
||||
|
||||
# It requires at least one test
|
||||
@@ -70,3 +66,75 @@ class TestAtomEditorComponentsSandbox(object):
|
||||
null_renderer=True,
|
||||
cfg_args=cfg_args,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_generic'])
|
||||
@pytest.mark.system
|
||||
class TestMaterialEditorBasicTests(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project):
|
||||
def delete_files():
|
||||
file_system.delete(
|
||||
[
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material.material"),
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material_1.material"),
|
||||
os.path.join(workspace.paths.project(), "Materials", "test_material_2.material"),
|
||||
],
|
||||
True,
|
||||
True,
|
||||
)
|
||||
# Cleanup our newly created materials
|
||||
delete_files()
|
||||
|
||||
def teardown():
|
||||
# Cleanup our newly created materials
|
||||
delete_files()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@pytest.mark.parametrize("exe_file_name", ["MaterialEditor"])
|
||||
@pytest.mark.test_case_id("C34448113") # Creating a New Asset.
|
||||
@pytest.mark.test_case_id("C34448114") # Opening an Existing Asset.
|
||||
@pytest.mark.test_case_id("C34448115") # Closing Selected Material.
|
||||
@pytest.mark.test_case_id("C34448116") # Closing All Materials.
|
||||
@pytest.mark.test_case_id("C34448117") # Closing all but Selected Material.
|
||||
@pytest.mark.test_case_id("C34448118") # Saving Material.
|
||||
@pytest.mark.test_case_id("C34448119") # Saving as a New Material.
|
||||
@pytest.mark.test_case_id("C34448120") # Saving as a Child Material.
|
||||
@pytest.mark.test_case_id("C34448121") # Saving all Open Materials.
|
||||
def test_MaterialEditorBasicTests(
|
||||
self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name):
|
||||
|
||||
expected_lines = [
|
||||
"Material opened: True",
|
||||
"Test asset doesn't exist initially: True",
|
||||
"New asset created: True",
|
||||
"New Material opened: True",
|
||||
"Material closed: True",
|
||||
"All documents closed: True",
|
||||
"Close All Except Selected worked as expected: True",
|
||||
"Actual Document saved with changes: True",
|
||||
"Document saved as copy is saved with changes: True",
|
||||
"Document saved as child is saved with changes: True",
|
||||
"Save All worked as expected: True",
|
||||
]
|
||||
unexpected_lines = [
|
||||
# "Trace::Assert",
|
||||
# "Trace::Error",
|
||||
"Traceback (most recent call last):"
|
||||
]
|
||||
|
||||
hydra.launch_and_validate_results(
|
||||
request,
|
||||
TEST_DIRECTORY,
|
||||
generic_launcher,
|
||||
"hydra_AtomMaterialEditor_BasicTests.py",
|
||||
run_python="--runpython",
|
||||
timeout=120,
|
||||
expected_lines=expected_lines,
|
||||
unexpected_lines=unexpected_lines,
|
||||
halt_on_unexpected=True,
|
||||
null_renderer=True,
|
||||
log_file_name="MaterialEditor.log",
|
||||
)
|
||||
|
||||
|
||||
@@ -17,3 +17,392 @@ LIGHT_TYPES = {
|
||||
'simple_point': 6,
|
||||
'simple_spot': 7,
|
||||
}
|
||||
|
||||
|
||||
class AtomComponentProperties:
|
||||
"""
|
||||
Holds Atom component related constants
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def actor(property: str = 'name') -> str:
|
||||
"""
|
||||
Actor component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Actor',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def bloom(property: str = 'name') -> str:
|
||||
"""
|
||||
Bloom component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Bloom',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def camera(property: str = 'name') -> str:
|
||||
"""
|
||||
Camera component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Camera',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def decal(property: str = 'name') -> str:
|
||||
"""
|
||||
Decal component properties.
|
||||
- 'Material' the material Asset.id of the decal.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Decal',
|
||||
'Material': 'Controller|Configuration|Material',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def deferred_fog(property: str = 'name') -> str:
|
||||
"""
|
||||
Deferred Fog component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Deferred Fog',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def depth_of_field(property: str = 'name') -> str:
|
||||
"""
|
||||
Depth of Field component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
- 'Camera Entity' an EditorEntity.id reference to the Camera component required for this effect.
|
||||
Must be a different entity than the one which hosts Depth of Field component.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'DepthOfField',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
'Camera Entity': 'Controller|Configuration|Camera Entity',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def diffuse_probe(property: str = 'name') -> str:
|
||||
"""
|
||||
Diffuse Probe Grid component properties. Requires one of 'shapes'.
|
||||
- 'shapes' a list of supported shapes as component names.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Diffuse Probe Grid',
|
||||
'shapes': ['Axis Aligned Box Shape', 'Box Shape']
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def directional_light(property: str = 'name') -> str:
|
||||
"""
|
||||
Directional Light component properties.
|
||||
- 'Camera' an EditorEntity.id reference to the Camera component that controls cascaded shadow view frustum.
|
||||
Must be a different entity than the one which hosts Directional Light component.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Directional Light',
|
||||
'Camera': 'Controller|Configuration|Shadow|Camera',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def display_mapper(property: str = 'name') -> str:
|
||||
"""
|
||||
Display Mapper component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Display Mapper',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def entity_reference(property: str = 'name') -> str:
|
||||
"""
|
||||
Entity Reference component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Entity Reference',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def exposure_control(property: str = 'name') -> str:
|
||||
"""
|
||||
Exposure Control component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Exposure Control',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def global_skylight(property: str = 'name') -> str:
|
||||
"""
|
||||
Global Skylight (IBL) component properties.
|
||||
- 'Diffuse Image' Asset.id for the cubemap image for determining diffuse lighting.
|
||||
- 'Specular Image' Asset.id for the cubemap image for determining specular lighting.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Global Skylight (IBL)',
|
||||
'Diffuse Image': 'Controller|Configuration|Diffuse Image',
|
||||
'Specular Image': 'Controller|Configuration|Specular Image',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def grid(property: str = 'name') -> str:
|
||||
"""
|
||||
Grid component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Grid',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def hdr_color_grading(property: str = 'name') -> str:
|
||||
"""
|
||||
HDR Color Grading component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'HDR Color Grading',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def hdri_skybox(property: str = 'name') -> str:
|
||||
"""
|
||||
HDRi Skybox component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'HDRi Skybox',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def light(property: str = 'name') -> str:
|
||||
"""
|
||||
Light component properties.
|
||||
- 'Light type' from atom_constants.py LIGHT_TYPES
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Light',
|
||||
'Light type': 'Controller|Configuration|Light type',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def look_modification(property: str = 'name') -> str:
|
||||
"""
|
||||
Look Modification component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Look Modification',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def material(property: str = 'name') -> str:
|
||||
"""
|
||||
Material component properties. Requires one of Actor OR Mesh component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Only one of these is required at a time for this component.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Material',
|
||||
'requires': [AtomComponentProperties.actor(), AtomComponentProperties.mesh()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def mesh(property: str = 'name') -> str:
|
||||
"""
|
||||
Mesh component properties.
|
||||
- 'Mesh Asset' Asset.id of the mesh model.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
:rtype: str
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Mesh',
|
||||
'Mesh Asset': 'Controller|Configuration|Mesh Asset',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def occlusion_culling_plane(property: str = 'name') -> str:
|
||||
"""
|
||||
Occlusion Culling Plane component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Occlusion Culling Plane',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def physical_sky(property: str = 'name') -> str:
|
||||
"""
|
||||
Physical Sky component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Physical Sky',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def postfx_layer(property: str = 'name') -> str:
|
||||
"""
|
||||
PostFX Layer component properties.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'PostFX Layer',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def postfx_gradient(property: str = 'name') -> str:
|
||||
"""
|
||||
PostFX Gradient Weight Modifier component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'PostFX Gradient Weight Modifier',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def postfx_radius(property: str = 'name') -> str:
|
||||
"""
|
||||
PostFX Radius Weight Modifier component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'PostFX Radius Weight Modifier',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def postfx_shape(property: str = 'name') -> str:
|
||||
"""
|
||||
PostFX Shape Weight Modifier component properties. Requires PostFX Layer and one of 'shapes' listed.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
- 'shapes' a list of supported shapes as component names. 'Tube Shape' is also supported but requires 'Spline'.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'PostFX Shape Weight Modifier',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
'shapes': ['Axis Aligned Box Shape', 'Box Shape', 'Capsule Shape', 'Compound Shape', 'Cylinder Shape',
|
||||
'Disk Shape', 'Polygon Prism Shape', 'Quad Shape', 'Sphere Shape', 'Vegetation Reference Shape'],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def reflection_probe(property: str = 'name') -> str:
|
||||
"""
|
||||
Reflection Probe component properties. Requires one of 'shapes' listed.
|
||||
- 'shapes' a list of supported shapes as component names.
|
||||
- 'Baked Cubemap Path' Asset.id of the baked cubemap image generated by a call to 'BakeReflectionProbe' ebus.
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'Reflection Probe',
|
||||
'shapes': ['Axis Aligned Box Shape', 'Box Shape'],
|
||||
'Baked Cubemap Path': 'Cubemap|Baked Cubemap Path',
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
@staticmethod
|
||||
def ssao(property: str = 'name') -> str:
|
||||
"""
|
||||
SSAO component properties. Requires PostFX Layer component.
|
||||
- 'requires' a list of component names as strings required by this component.
|
||||
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
|
||||
:param property: From the last element of the property tree path. Default 'name' for component name string.
|
||||
:return: Full property path OR component name if no property specified.
|
||||
"""
|
||||
properties = {
|
||||
'name': 'SSAO',
|
||||
'requires': [AtomComponentProperties.postfx_layer()],
|
||||
}
|
||||
return properties[property]
|
||||
|
||||
+12
-13
@@ -80,25 +80,25 @@ def AtomEditorComponents_Mesh_AddedToEntity():
|
||||
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties as Atom
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
helper.init_idle()
|
||||
helper.open_level("", "Base")
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create a Mesh entity with no components.
|
||||
mesh_name = "Mesh"
|
||||
mesh_entity = EditorEntity.create_editor_entity(mesh_name)
|
||||
mesh_entity = EditorEntity.create_editor_entity(Atom.mesh())
|
||||
Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists())
|
||||
|
||||
# 2. Add a Mesh component to Mesh entity.
|
||||
mesh_component = mesh_entity.add_component(mesh_name)
|
||||
mesh_component = mesh_entity.add_component(Atom.mesh())
|
||||
Report.critical_result(
|
||||
Tests.mesh_component_added,
|
||||
mesh_entity.has_component(mesh_name))
|
||||
mesh_entity.has_component(Atom.mesh()))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
@@ -125,17 +125,16 @@ def AtomEditorComponents_Mesh_AddedToEntity():
|
||||
Report.result(Tests.creation_redo, mesh_entity.exists())
|
||||
|
||||
# 5. Set Mesh component asset property
|
||||
mesh_property_asset = 'Controller|Configuration|Mesh Asset'
|
||||
model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel')
|
||||
model = Asset.find_asset_by_path(model_path)
|
||||
mesh_component.set_component_property_value(mesh_property_asset, model.id)
|
||||
mesh_component.set_component_property_value(Atom.mesh('Mesh Asset'), model.id)
|
||||
Report.result(Tests.mesh_asset_specified,
|
||||
mesh_component.get_component_property_value(mesh_property_asset) == model.id)
|
||||
mesh_component.get_component_property_value(Atom.mesh('Mesh Asset')) == model.id)
|
||||
|
||||
# 6. Enter/Exit game mode.
|
||||
helper.enter_game_mode(Tests.enter_game_mode)
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 7. Test IsHidden.
|
||||
mesh_entity.set_visibility_state(False)
|
||||
@@ -159,7 +158,7 @@ def AtomEditorComponents_Mesh_AddedToEntity():
|
||||
Report.result(Tests.deletion_redo, not mesh_entity.exists())
|
||||
|
||||
# 12. Look for errors or asserts.
|
||||
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
|
||||
-1
@@ -90,7 +90,6 @@ def run():
|
||||
benchmarker.capture_cpu_frame_time(i)
|
||||
general.exit_game_mode()
|
||||
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0)
|
||||
general.log("Capturing complete.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -215,7 +215,6 @@ def run():
|
||||
ScreenshotHelper(general.idle_wait_frames).capture_screenshot_blocking(f"{'AtomBasicLevelSetup'}.ppm")
|
||||
general.exit_game_mode()
|
||||
helper.wait_for_condition(function=lambda: not general.is_in_game_mode(), timeout_in_seconds=2.0)
|
||||
general.log("Basic level created")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -33,7 +33,7 @@ add_subdirectory(WhiteBox)
|
||||
add_subdirectory(NvCloth)
|
||||
|
||||
## Prefab ##
|
||||
add_subdirectory(prefab)
|
||||
add_subdirectory(Prefab)
|
||||
|
||||
## Editor Python Bindings ##
|
||||
add_subdirectory(EditorPythonBindings)
|
||||
@@ -58,3 +58,6 @@ add_subdirectory(smoke)
|
||||
|
||||
## AWS ##
|
||||
add_subdirectory(AWS)
|
||||
|
||||
## Integration tests for editor testing framework ##
|
||||
add_subdirectory(editor_test_testing)
|
||||
|
||||
+26
-6
@@ -122,17 +122,32 @@ class EditorEntity:
|
||||
|
||||
# Creation functions
|
||||
@classmethod
|
||||
def find_editor_entity(cls, entity_name: str) -> EditorEntity:
|
||||
def find_editor_entity(cls, entity_name: str, must_be_unique : bool = False) -> EditorEntity:
|
||||
"""
|
||||
Given Entity name, outputs entity object
|
||||
:param entity_name: Name of entity to find
|
||||
:return: EditorEntity class object
|
||||
"""
|
||||
entity_id = general.find_editor_entity(entity_name)
|
||||
assert entity_id.IsValid(), f"Failure: Couldn't find entity with name: '{entity_name}'"
|
||||
entity = cls(entity_id)
|
||||
entities = cls.find_editor_entities([entity_name])
|
||||
assert len(entities) != 0, f"Failure: Couldn't find entity with name: '{entity_name}'"
|
||||
if must_be_unique:
|
||||
assert len(entities) == 1, f"Failure: Multiple entities with name: '{entity_name}' when expected only one"
|
||||
|
||||
entity = cls(entities[0])
|
||||
return entity
|
||||
|
||||
@classmethod
|
||||
def find_editor_entities(cls, entity_names: List[str]) -> EditorEntity:
|
||||
"""
|
||||
Given Entities names, returns a list of EditorEntity
|
||||
:param entity_name: Name of entity to find
|
||||
:return: List[EditorEntity] class object
|
||||
"""
|
||||
searchFilter = azlmbr.entity.SearchFilter()
|
||||
searchFilter.names = entity_names
|
||||
ids = azlmbr.entity.SearchBus(bus.Broadcast, 'SearchEntities', searchFilter)
|
||||
return [cls(id) for id in ids]
|
||||
|
||||
@classmethod
|
||||
def create_editor_entity(cls, name: str = None, parent_id=None) -> EditorEntity:
|
||||
"""
|
||||
@@ -157,8 +172,7 @@ class EditorEntity:
|
||||
cls,
|
||||
entity_position: Union[List, Tuple, math.Vector3],
|
||||
name: str = None,
|
||||
parent_id: azlmbr.entity.EntityId = None,
|
||||
) -> EditorEntity:
|
||||
parent_id: azlmbr.entity.EntityId = None) -> EditorEntity:
|
||||
"""
|
||||
Used to create entity at position using 'CreateNewEntityAtPosition' Bus.
|
||||
:param entity_position: World Position(X, Y, Z) of entity in viewport.
|
||||
@@ -227,6 +241,12 @@ class EditorEntity:
|
||||
"""
|
||||
return editor.EditorEntityInfoRequestBus(bus.Event, "GetChildren", self.id)
|
||||
|
||||
def get_children(self) -> List[EditorEntity]:
|
||||
"""
|
||||
:return: List of EditorEntity children. Type: [EditorEntity]
|
||||
"""
|
||||
return [EditorEntity(child_id) for child_id in self.get_children_ids()]
|
||||
|
||||
def add_component(self, component_name: str) -> EditorComponent:
|
||||
"""
|
||||
Used to add new component to Entity.
|
||||
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from collections import Counter
|
||||
from collections import deque
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
from azlmbr.entity import EntityId
|
||||
from azlmbr.math import Vector3
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report
|
||||
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.globals
|
||||
import azlmbr.math as math
|
||||
import azlmbr.prefab as prefab
|
||||
import editor_python_test_tools.pyside_utils as pyside_utils
|
||||
|
||||
|
||||
def get_prefab_file_path(prefab_path):
|
||||
if not path.isabs(prefab_path):
|
||||
prefab_path = path.join(general.get_file_alias("@projectroot@"), prefab_path)
|
||||
|
||||
# Append prefab if it doesn't contain .prefab on it
|
||||
name, ext = path.splitext(prefab_path)
|
||||
if ext != ".prefab":
|
||||
prefab_path = name + ".prefab"
|
||||
return prefab_path
|
||||
|
||||
|
||||
def get_all_entity_ids():
|
||||
return entity.SearchBus(bus.Broadcast, 'SearchEntities', entity.SearchFilter())
|
||||
|
||||
def wait_for_propagation():
|
||||
general.idle_wait_frames(1)
|
||||
|
||||
# This is a helper class which contains some of the useful information about a prefab instance.
|
||||
class PrefabInstance:
|
||||
|
||||
def __init__(self, prefab_file_name: str = None, container_entity: EditorEntity = None):
|
||||
self.prefab_file_name: str = prefab_file_name
|
||||
self.container_entity: EditorEntity = container_entity
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.container_entity.id == other.container_entity.id
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.container_entity.id)
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
"""
|
||||
See if this instance is valid to be used with other prefab operations.
|
||||
:return: Whether the target instance is valid or not.
|
||||
"""
|
||||
return self.container_entity.id.IsValid() and self.prefab_file_name in Prefab.existing_prefabs
|
||||
|
||||
def has_editor_prefab_component(self) -> bool:
|
||||
"""
|
||||
Check if the instance's container entity contains EditorPrefabComponent.
|
||||
:return: Whether the container entity of target instance has EditorPrefabComponent in it or not.
|
||||
"""
|
||||
return editor.EditorComponentAPIBus(bus.Broadcast, "HasComponentOfType", self.container_entity.id, azlmbr.globals.property.EditorPrefabComponentTypeId)
|
||||
|
||||
def is_at_position(self, expected_position):
|
||||
"""
|
||||
Check if the instance's container entity is at expected position given.
|
||||
:return: Whether the container entity of target instance is at expected position or not.
|
||||
"""
|
||||
actual_position = components.TransformBus(bus.Event, "GetWorldTranslation", self.container_entity.id)
|
||||
is_at_position = actual_position.IsClose(expected_position)
|
||||
|
||||
if not is_at_position:
|
||||
Report.info(f"Prefab Instance Container Entity '{self.container_entity.id.ToString()}'\'s expected position: {expected_position.ToString()}, actual position: {actual_position.ToString()}")
|
||||
|
||||
return is_at_position
|
||||
|
||||
async def ui_reparent_prefab_instance(self, parent_entity_id: EntityId):
|
||||
"""
|
||||
Reparent this instance to target parent entity.
|
||||
The function will also check pop up dialog ui in editor to see if there's prefab cyclical dependency error while reparenting prefabs.
|
||||
:param parent_entity_id: The id of the entity this instance should be a child of in the transform hierarchy next.
|
||||
"""
|
||||
container_entity_id_before_reparent = self.container_entity.id
|
||||
|
||||
original_parent = EditorEntity(self.container_entity.get_parent_id())
|
||||
original_parent_before_reparent_children_ids = {child_id.ToString(): child_id for child_id in original_parent.get_children_ids()}
|
||||
|
||||
new_parent = EditorEntity(parent_entity_id)
|
||||
new_parent_before_reparent_children_ids = {child_id.ToString(): child_id for child_id in new_parent.get_children_ids()}
|
||||
|
||||
pyside_utils.run_soon(lambda: self.container_entity.set_parent_entity(parent_entity_id))
|
||||
pyside_utils.run_soon(lambda: wait_for_propagation())
|
||||
|
||||
try:
|
||||
active_modal_widget = await pyside_utils.wait_for_modal_widget()
|
||||
error_message_box = active_modal_widget.findChild(QtWidgets.QMessageBox)
|
||||
ok_button = error_message_box.button(QtWidgets.QMessageBox.Ok)
|
||||
ok_button.click()
|
||||
assert False, "Cyclical dependency detected while reparenting prefab"
|
||||
except pyside_utils.EventLoopTimeoutException:
|
||||
pass
|
||||
|
||||
original_parent_after_reparent_children_ids = {child_id.ToString(): child_id for child_id in original_parent.get_children_ids()}
|
||||
assert len(original_parent_after_reparent_children_ids) == len(original_parent_before_reparent_children_ids) - 1, \
|
||||
"The children count of the Prefab Instance's original parent should be decreased by 1."
|
||||
assert not container_entity_id_before_reparent in original_parent_after_reparent_children_ids, \
|
||||
"This Prefab Instance is still a child entity of its original parent entity."
|
||||
|
||||
new_parent_after_reparent_children_ids = {child_id.ToString(): child_id for child_id in new_parent.get_children_ids()}
|
||||
assert len(new_parent_after_reparent_children_ids) == len(new_parent_before_reparent_children_ids) + 1, \
|
||||
"The children count of the Prefab Instance's new parent should be increased by 1."
|
||||
|
||||
after_before_diff = set(new_parent_after_reparent_children_ids.keys()).difference(set(new_parent_before_reparent_children_ids.keys()))
|
||||
container_entity_id_after_reparent = new_parent_after_reparent_children_ids[after_before_diff.pop()]
|
||||
reparented_container_entity = EditorEntity(container_entity_id_after_reparent)
|
||||
reparented_container_entity_parent_id = reparented_container_entity.get_parent_id()
|
||||
has_correct_parent = reparented_container_entity_parent_id.ToString() == parent_entity_id.ToString()
|
||||
assert has_correct_parent, "Prefab Instance reparented is *not* under the expected parent entity"
|
||||
|
||||
current_instance_prefab = Prefab.get_prefab(self.prefab_file_name)
|
||||
current_instance_prefab.instances.remove(self)
|
||||
|
||||
self.container_entity = reparented_container_entity
|
||||
current_instance_prefab.instances.add(self)
|
||||
|
||||
# This is a helper class which contains some of the useful information about a prefab template.
|
||||
class Prefab:
|
||||
|
||||
existing_prefabs = {}
|
||||
|
||||
def __init__(self, file_path: str):
|
||||
self.file_path: str = get_prefab_file_path(file_path)
|
||||
self.instances: set[PrefabInstance] = set()
|
||||
|
||||
@classmethod
|
||||
def is_prefab_loaded(cls, file_path: str) -> bool:
|
||||
"""
|
||||
Check if a prefab is ready to be used to generate its instances.
|
||||
:param file_path: A unique file path of the target prefab.
|
||||
:return: Whether the target prefab is loaded or not.
|
||||
"""
|
||||
return file_path in Prefab.existing_prefabs
|
||||
|
||||
|
||||
@classmethod
|
||||
def prefab_exists(cls, file_path: str) -> bool:
|
||||
"""
|
||||
Check if a prefab exists in the directory for files of prefab tests.
|
||||
:param file_name: A unique file name of the target prefab.
|
||||
:return: Whether the target prefab exists or not.
|
||||
"""
|
||||
return path.exists(get_prefab_file_path(file_path))
|
||||
|
||||
@classmethod
|
||||
def get_prefab(cls, file_name: str) -> Prefab:
|
||||
"""
|
||||
Return a prefab which can be used immediately.
|
||||
:param file_name: A unique file name of the target prefab.
|
||||
:return: The prefab with given file name.
|
||||
"""
|
||||
assert file_name, "Received an empty file_name"
|
||||
if Prefab.is_prefab_loaded(file_name):
|
||||
return Prefab.existing_prefabs[file_name]
|
||||
else:
|
||||
assert Prefab.prefab_exists(file_name), f"Attempted to get a prefab \"{file_name}\" that doesn't exist"
|
||||
new_prefab = Prefab(file_name)
|
||||
Prefab.existing_prefabs[file_name] = Prefab(file_name)
|
||||
return new_prefab
|
||||
|
||||
@classmethod
|
||||
def create_prefab(cls, entities: list[EditorEntity], file_name: str, prefab_instance_name: str=None) -> tuple(Prefab, PrefabInstance):
|
||||
"""
|
||||
Create a prefab in memory and return it. The very first instance of this prefab will also be created.
|
||||
:param entities: The entities that should form the new prefab (along with their descendants).
|
||||
:param file_name: A unique file name of new prefab.
|
||||
:param prefab_instance_name: A name for the very first instance generated while prefab creation. The default instance name is the same as file_name.
|
||||
:return: Created Prefab object and the very first PrefabInstance object owned by the prefab.
|
||||
"""
|
||||
assert not Prefab.is_prefab_loaded(file_name), f"Can't create Prefab '{file_name}' since the prefab already exists"
|
||||
|
||||
new_prefab = Prefab(file_name)
|
||||
entity_ids = [entity.id for entity in entities]
|
||||
create_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'CreatePrefabInMemory', entity_ids, new_prefab.file_path)
|
||||
assert create_prefab_result.IsSuccess(), f"Prefab operation 'CreatePrefab' failed. Error: {create_prefab_result.GetError()}"
|
||||
|
||||
container_entity_id = create_prefab_result.GetValue()
|
||||
container_entity = EditorEntity(container_entity_id)
|
||||
children_entity_ids = container_entity.get_children_ids()
|
||||
|
||||
assert len(children_entity_ids) == len(entities), f"Entity count of created prefab instance does *not* match the count of given entities."
|
||||
|
||||
if prefab_instance_name:
|
||||
container_entity.set_name(prefab_instance_name)
|
||||
|
||||
wait_for_propagation()
|
||||
|
||||
new_prefab_instance = PrefabInstance(file_name, EditorEntity(container_entity_id))
|
||||
new_prefab.instances.add(new_prefab_instance)
|
||||
Prefab.existing_prefabs[file_name] = new_prefab
|
||||
return new_prefab, new_prefab_instance
|
||||
|
||||
@classmethod
|
||||
def remove_prefabs(cls, prefab_instances: list[PrefabInstance]):
|
||||
"""
|
||||
Remove target prefab instances.
|
||||
:param prefab_instances: Instances to be removed.
|
||||
"""
|
||||
entity_ids_to_remove = []
|
||||
entity_id_queue = [prefab_instance.container_entity for prefab_instance in prefab_instances]
|
||||
while entity_id_queue:
|
||||
entity = entity_id_queue.pop(0)
|
||||
children_entity_ids = entity.get_children_ids()
|
||||
for child_entity_id in children_entity_ids:
|
||||
entity_id_queue.append(EditorEntity(child_entity_id))
|
||||
|
||||
entity_ids_to_remove.append(entity.id)
|
||||
|
||||
container_entity_ids = [prefab_instance.container_entity.id for prefab_instance in prefab_instances]
|
||||
delete_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'DeleteEntitiesAndAllDescendantsInInstance', container_entity_ids)
|
||||
assert delete_prefab_result.IsSuccess(), f"Prefab operation 'DeleteEntitiesAndAllDescendantsInInstance' failed. Error: {delete_prefab_result.GetError()}"
|
||||
|
||||
wait_for_propagation()
|
||||
|
||||
entity_ids_after_delete = set(get_all_entity_ids())
|
||||
|
||||
for entity_id_removed in entity_ids_to_remove:
|
||||
if entity_id_removed in entity_ids_after_delete:
|
||||
assert False, "Not all entities and descendants in target prefabs are deleted."
|
||||
|
||||
for instance in prefab_instances:
|
||||
instance_deleted_prefab = Prefab.get_prefab(instance.prefab_file_name)
|
||||
instance_deleted_prefab.instances.remove(instance)
|
||||
instance = PrefabInstance()
|
||||
|
||||
@classmethod
|
||||
def duplicate_prefabs(cls, prefab_instances: list[PrefabInstance]):
|
||||
"""
|
||||
Duplicate target prefab instances.
|
||||
:param prefab_instances: Instances to be duplicated.
|
||||
:return: PrefabInstance objects of given prefab instances' duplicates.
|
||||
"""
|
||||
assert prefab_instances, "Input list of prefab instances should *not* be empty."
|
||||
|
||||
common_parent = EditorEntity(prefab_instances[0].container_entity.get_parent_id())
|
||||
common_parent_children_ids_before_duplicate = set([child_id.ToString() for child_id in common_parent.get_children_ids()])
|
||||
|
||||
container_entity_ids = [prefab_instance.container_entity.id for prefab_instance in prefab_instances]
|
||||
|
||||
duplicate_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'DuplicateEntitiesInInstance', container_entity_ids)
|
||||
assert duplicate_prefab_result.IsSuccess(), f"Prefab operation 'DuplicateEntitiesInInstance' failed. Error: {duplicate_prefab_result.GetError()}"
|
||||
|
||||
wait_for_propagation()
|
||||
|
||||
duplicate_container_entity_ids = duplicate_prefab_result.GetValue()
|
||||
common_parent_children_ids_after_duplicate = set([child_id.ToString() for child_id in common_parent.get_children_ids()])
|
||||
|
||||
assert set([container_entity_id.ToString() for container_entity_id in container_entity_ids]).issubset(common_parent_children_ids_after_duplicate), \
|
||||
"Provided prefab instances are *not* the children of their common parent anymore after duplication."
|
||||
assert common_parent_children_ids_before_duplicate.issubset(common_parent_children_ids_after_duplicate), \
|
||||
"Some children of provided entities' common parent before duplication are *not* the children of the common parent anymore after duplication."
|
||||
assert len(common_parent_children_ids_after_duplicate) == len(common_parent_children_ids_before_duplicate) + len(prefab_instances), \
|
||||
"The children count of the given prefab instances' common parent entity is *not* increased to the expected number."
|
||||
assert EditorEntity(duplicate_container_entity_ids[0]).get_parent_id().ToString() == common_parent.id.ToString(), \
|
||||
"Provided prefab instances' parent should be the same as duplicates' parent."
|
||||
|
||||
duplicate_instances = []
|
||||
for duplicate_container_entity_id in duplicate_container_entity_ids:
|
||||
prefab_file_path = prefab.PrefabPublicRequestBus(bus.Broadcast, 'GetOwningInstancePrefabPath', duplicate_container_entity_id)
|
||||
assert prefab_file_path, "Returned file path should *not* be empty."
|
||||
|
||||
prefab_file_name = Path(prefab_file_path).stem
|
||||
duplicate_instance_prefab = Prefab.get_prefab(prefab_file_name)
|
||||
duplicate_instance = PrefabInstance(prefab_file_path, EditorEntity(duplicate_container_entity_id))
|
||||
duplicate_instance_prefab.instances.add(duplicate_instance)
|
||||
duplicate_instances.append(duplicate_instance)
|
||||
|
||||
return duplicate_instances
|
||||
|
||||
@classmethod
|
||||
def detach_prefab(cls, prefab_instance: PrefabInstance):
|
||||
"""
|
||||
Detach target prefab instance.
|
||||
:param prefab_instances: Instance to be detached.
|
||||
"""
|
||||
parent = EditorEntity(prefab_instance.container_entity.get_parent_id())
|
||||
parent_children_ids_before_detach = set([child_id.ToString() for child_id in parent.get_children_ids()])
|
||||
|
||||
assert prefab_instance.has_editor_prefab_component(), f"Container entity should have EditorPrefabComponent before detachment."
|
||||
|
||||
detach_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'DetachPrefab', prefab_instance.container_entity.id)
|
||||
assert detach_prefab_result.IsSuccess(), f"Prefab operation 'DetachPrefab' failed. Error: {detach_prefab_result.GetError()}"
|
||||
|
||||
assert not prefab_instance.has_editor_prefab_component(), f"Container entity should *not* have EditorPrefabComponent after detachment."
|
||||
|
||||
parent_children_ids_after_detach = set([child_id.ToString() for child_id in parent.get_children_ids()])
|
||||
|
||||
assert prefab_instance.container_entity.id.ToString() in parent_children_ids_after_detach, \
|
||||
"Target prefab instance's container entity id should still exists after the detachment and before the propagation."
|
||||
|
||||
assert len(parent_children_ids_after_detach) == len(parent_children_ids_before_detach), \
|
||||
"Parent entity should still keep the same amount of children entities."
|
||||
|
||||
wait_for_propagation()
|
||||
|
||||
instance_owner_prefab = Prefab.get_prefab(prefab_instance.prefab_file_name)
|
||||
instance_owner_prefab.instances.remove(prefab_instance)
|
||||
prefab_instance = PrefabInstance()
|
||||
|
||||
def instantiate(self, parent_entity: EditorEntity=None, name: str=None, prefab_position: Vector3=Vector3()) -> PrefabInstance:
|
||||
"""
|
||||
Instantiate an instance of this prefab.
|
||||
:param parent_entity: The entity the prefab should be a child of in the transform hierarchy.
|
||||
:param name: A name for newly instantiated prefab instance. The default instance name is the same as this prefab's file name.
|
||||
:param prefab_position: The position in world space the prefab should be instantiated in.
|
||||
:return: Instantiated PrefabInstance object owned by this prefab.
|
||||
"""
|
||||
parent_entity_id = parent_entity.id if parent_entity is not None else EntityId()
|
||||
|
||||
instantiate_prefab_result = prefab.PrefabPublicRequestBus(
|
||||
bus.Broadcast, 'InstantiatePrefab', self.file_path, parent_entity_id, prefab_position)
|
||||
|
||||
assert instantiate_prefab_result.IsSuccess(), f"Prefab operation 'InstantiatePrefab' failed. Error: {instantiate_prefab_result.GetError()}"
|
||||
|
||||
container_entity_id = instantiate_prefab_result.GetValue()
|
||||
container_entity = EditorEntity(container_entity_id)
|
||||
|
||||
if name:
|
||||
container_entity.set_name(name)
|
||||
|
||||
wait_for_propagation()
|
||||
|
||||
new_prefab_instance = PrefabInstance(self.file_path, EditorEntity(container_entity_id))
|
||||
assert not new_prefab_instance in self.instances, "This prefab instance is already existed before this instantiation."
|
||||
self.instances.add(new_prefab_instance)
|
||||
|
||||
assert new_prefab_instance.is_at_position(prefab_position), "This prefab instance is *not* at expected position."
|
||||
|
||||
return new_prefab_instance
|
||||
@@ -9,20 +9,17 @@ import pytest
|
||||
import sys
|
||||
|
||||
import ly_test_tools.environment.file_system as fs
|
||||
from .FileManagement import FileManagement as fm
|
||||
from .utils.FileManagement import FileManagement as fm
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared')
|
||||
|
||||
from .base import TestAutomationBase
|
||||
from base import TestAutomationBase
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["win_x64_vs2017"])
|
||||
@pytest.mark.parametrize("configuration", ["profile"])
|
||||
@pytest.mark.parametrize("spec", ["all"])
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
class TestUtils(TestAutomationBase):
|
||||
@fm.file_revert("UtilTest_Physmaterial_Editor_TestLibrary.physmaterial", r"AutomatedTesting\Levels\Physics\Physmaterial_Editor_Test")
|
||||
def test_physmaterial_editor(self, request, workspace, editor):
|
||||
def test_physmaterial_editor(self, request, workspace, launcher_platform, editor):
|
||||
"""
|
||||
Tests functionality of physmaterial editing utility
|
||||
:param workspace: Fixture containing platform and project detail
|
||||
@@ -35,11 +32,11 @@ class TestUtils(TestAutomationBase):
|
||||
unexpected_lines = ["Assert"]
|
||||
self._run_test(request, workspace, editor, physmaterial_editor_test_module, expected_lines, unexpected_lines)
|
||||
|
||||
def test_UtilTest_Tracer_PicksErrorsAndWarnings(self, request, workspace, editor):
|
||||
def test_UtilTest_Tracer_PicksErrorsAndWarnings(self, request, workspace, launcher_platform, editor):
|
||||
from .utils import UtilTest_Tracer_PicksErrorsAndWarnings as testcase_module
|
||||
self._run_test(request, workspace, editor, testcase_module, [], [])
|
||||
|
||||
def test_FileManagement_FindingFiles(self, workspace):
|
||||
def test_FileManagement_FindingFiles(self, workspace, launcher_platform):
|
||||
"""
|
||||
Tests the functionality of "searching for files" with FileManagement._find_files()
|
||||
:param workspace: ly_test_tools workspace fixture
|
||||
@@ -110,7 +107,7 @@ class TestUtils(TestAutomationBase):
|
||||
find_me_too_path, found_me["FindMeToo.txt"]
|
||||
)
|
||||
|
||||
def test_FileManagement_FileBackup(self, workspace):
|
||||
def test_FileManagement_FileBackup(self, workspace, launcher_platform):
|
||||
"""
|
||||
Tests the functionality of the file back up system via the FileManagement class
|
||||
:param workspace: ly_test_tools workspace fixture
|
||||
@@ -167,7 +164,7 @@ class TestUtils(TestAutomationBase):
|
||||
del file_map[target_file_path]
|
||||
fm._save_file_map(file_map)
|
||||
|
||||
def test_FileManagement_FileRestoration(self, workspace):
|
||||
def test_FileManagement_FileRestoration(self, workspace, launcher_platform):
|
||||
"""
|
||||
Tests the restore file system via the FileManagement class
|
||||
:param workspace: ly_test_tools workspace fixture
|
||||
@@ -261,7 +258,7 @@ class TestUtils(TestAutomationBase):
|
||||
["FindMe.txt", "FindMeToo.txt"], parent_path=r"AutomatedTesting\levels\Utils\Managed_files", search_subdirs=True
|
||||
)
|
||||
@fm.file_override("default.physxconfiguration", "UtilTest_PhysxConfig_Override.physxconfiguration")
|
||||
def test_UtilTest_Managed_Files(self, request, workspace, editor):
|
||||
def test_UtilTest_Managed_Files(self, request, workspace, editor, launcher_platform):
|
||||
from .utils import UtilTest_Managed_Files as test_module
|
||||
|
||||
expected_lines = []
|
||||
|
||||
+17
-9
@@ -29,21 +29,29 @@ class TestAutomation(TestAutomationBase):
|
||||
autotest_mode=autotest_mode)
|
||||
|
||||
def test_PrefabLevel_OpensLevelWithEntities(self, request, workspace, editor, launcher_platform):
|
||||
from . import PrefabLevel_OpensLevelWithEntities as test_module
|
||||
from .tests import PrefabLevel_OpensLevelWithEntities as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_Prefab_BasicWorkflow_CreatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from . import Prefab_BasicWorkflow_CreatePrefab as test_module
|
||||
def test_PrefabBasicWorkflow_CreatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreatePrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_Prefab_BasicWorkflow_InstantiatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from . import Prefab_BasicWorkflow_InstantiatePrefab as test_module
|
||||
def test_PrefabBasicWorkflow_InstantiatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_InstantiatePrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_Prefab_BasicWorkflow_CreateAndDeletePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from . import Prefab_BasicWorkflow_CreateAndDeletePrefab as test_module
|
||||
def test_PrefabBasicWorkflow_CreateAndDeletePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndDeletePrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_Prefab_BasicWorkflow_CreateAndReparentPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from . import Prefab_BasicWorkflow_CreateAndReparentPrefab as test_module
|
||||
def test_PrefabBasicWorkflow_CreateAndReparentPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndReparentPrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateReparentAndDetachPrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateReparentAndDetachPrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
|
||||
|
||||
def test_PrefabBasicWorkflow_CreateAndDuplicatePrefab(self, request, workspace, editor, launcher_platform):
|
||||
from .tests import PrefabBasicWorkflow_CreateAndDuplicatePrefab as test_module
|
||||
self._run_prefab_test(request, workspace, editor, test_module)
|
||||
+7
-8
@@ -5,29 +5,28 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def Prefab_BasicWorkflow_CreateAndDeletePrefab():
|
||||
def PrefabBasicWorkflow_CreateAndDeletePrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from prefab.Prefab import Prefab
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import prefab.Prefab_Test_Utils as prefab_test_utils
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Creates a new Entity at the root level
|
||||
# Asserts if creation didn't succeed
|
||||
# Creates a new entity at the root level
|
||||
car_entity = EditorEntity.create_editor_entity()
|
||||
car_prefab_entities = [car_entity]
|
||||
|
||||
# Checks for prefab creation passed or not
|
||||
# Creates a prefab from the new entity
|
||||
_, car = Prefab.create_prefab(
|
||||
car_prefab_entities, CAR_PREFAB_FILE_NAME)
|
||||
|
||||
# Checks for prefab deletion passed or not
|
||||
# Deletes the prefab instance
|
||||
Prefab.remove_prefabs([car])
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Prefab_BasicWorkflow_CreateAndDeletePrefab)
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndDeletePrefab)
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateAndDuplicatePrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Creates a new entity at the root level
|
||||
car_entity = EditorEntity.create_editor_entity()
|
||||
car_prefab_entities = [car_entity]
|
||||
|
||||
# Creates a prefab from the new entity
|
||||
_, car = Prefab.create_prefab(
|
||||
car_prefab_entities, CAR_PREFAB_FILE_NAME)
|
||||
|
||||
# Duplicates the prefab instance
|
||||
Prefab.duplicate_prefabs([car])
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndDuplicatePrefab)
|
||||
+9
-10
@@ -5,7 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def Prefab_BasicWorkflow_CreateAndReparentPrefab():
|
||||
def PrefabBasicWorkflow_CreateAndReparentPrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab'
|
||||
@@ -16,34 +16,33 @@ def Prefab_BasicWorkflow_CreateAndReparentPrefab():
|
||||
async def run_test():
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from prefab.Prefab import Prefab
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import prefab.Prefab_Test_Utils as prefab_test_utils
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Creates a new Entity at the root level
|
||||
# Asserts if creation didn't succeed
|
||||
# Creates a new car entity at the root level
|
||||
car_entity = EditorEntity.create_editor_entity()
|
||||
car_prefab_entities = [car_entity]
|
||||
|
||||
# Checks for prefab creation passed or not
|
||||
# Creates a prefab from the car entity
|
||||
_, car = Prefab.create_prefab(
|
||||
car_prefab_entities, CAR_PREFAB_FILE_NAME)
|
||||
|
||||
# Creates another new Entity at the root level
|
||||
# Creates another new wheel entity at the root level
|
||||
wheel_entity = EditorEntity.create_editor_entity()
|
||||
wheel_prefab_entities = [wheel_entity]
|
||||
|
||||
# Checks for wheel prefab creation passed or not
|
||||
# Creates another prefab from the wheel entity
|
||||
_, wheel = Prefab.create_prefab(
|
||||
wheel_prefab_entities, WHEEL_PREFAB_FILE_NAME)
|
||||
|
||||
# Checks for prefab reparenting passed or not
|
||||
# Reparents the wheel prefab instance to the container entity of the car prefab instance
|
||||
await wheel.ui_reparent_prefab_instance(car.container_entity.id)
|
||||
|
||||
run_test()
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Prefab_BasicWorkflow_CreateAndReparentPrefab)
|
||||
Report.start_test(PrefabBasicWorkflow_CreateAndReparentPrefab)
|
||||
+6
-7
@@ -5,26 +5,25 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def Prefab_BasicWorkflow_CreatePrefab():
|
||||
def PrefabBasicWorkflow_CreatePrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report
|
||||
from prefab.Prefab import Prefab
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import prefab.Prefab_Test_Utils as prefab_test_utils
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Creates a new Entity at the root level
|
||||
# Asserts if creation didn't succeed
|
||||
# Creates a new entity at the root level
|
||||
car_entity = EditorEntity.create_editor_entity()
|
||||
car_prefab_entities = [car_entity]
|
||||
|
||||
# Checks for prefab creation passed or not
|
||||
# Creates a prefab from the new entity
|
||||
Prefab.create_prefab(car_prefab_entities, CAR_PREFAB_FILE_NAME)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Prefab_BasicWorkflow_CreatePrefab)
|
||||
Report.start_test(PrefabBasicWorkflow_CreatePrefab)
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
def PrefabBasicWorkflow_CreateReparentAndDetachPrefab():
|
||||
|
||||
CAR_PREFAB_FILE_NAME = 'car_prefab'
|
||||
WHEEL_PREFAB_FILE_NAME = 'wheel_prefab'
|
||||
|
||||
import editor_python_test_tools.pyside_utils as pyside_utils
|
||||
|
||||
@pyside_utils.wrap_async
|
||||
async def run_test():
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Creates a new car entity at the root level
|
||||
car_entity = EditorEntity.create_editor_entity()
|
||||
car_prefab_entities = [car_entity]
|
||||
|
||||
# Creates a prefab from the car entity
|
||||
_, car = Prefab.create_prefab(
|
||||
car_prefab_entities, CAR_PREFAB_FILE_NAME)
|
||||
|
||||
# Creates another new wheel entity at the root level
|
||||
wheel_entity = EditorEntity.create_editor_entity()
|
||||
wheel_prefab_entities = [wheel_entity]
|
||||
|
||||
# Creates another prefab from the wheel entity
|
||||
_, wheel = Prefab.create_prefab(
|
||||
wheel_prefab_entities, WHEEL_PREFAB_FILE_NAME)
|
||||
|
||||
# Reparents the wheel prefab instance to the container entity of the car prefab instance
|
||||
await wheel.ui_reparent_prefab_instance(car.container_entity.id)
|
||||
|
||||
# Detaches the wheel prefab instance
|
||||
Prefab.detach_prefab(wheel)
|
||||
|
||||
run_test()
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(PrefabBasicWorkflow_CreateReparentAndDetachPrefab)
|
||||
+6
-7
@@ -5,23 +5,22 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
def Prefab_BasicWorkflow_InstantiatePrefab():
|
||||
def PrefabBasicWorkflow_InstantiatePrefab():
|
||||
|
||||
from azlmbr.math import Vector3
|
||||
|
||||
EXISTING_TEST_PREFAB_FILE_NAME = "Test"
|
||||
EXISTING_TEST_PREFAB_FILE_NAME = "Gem/PythonTests/Prefab/data/Test.prefab"
|
||||
INSTANTIATED_TEST_PREFAB_POSITION = Vector3(10.00, 20.0, 30.0)
|
||||
EXPECTED_TEST_PREFAB_CHILDREN_COUNT = 1
|
||||
|
||||
from prefab.Prefab import Prefab
|
||||
from editor_python_test_tools.prefab_utils import Prefab
|
||||
|
||||
import prefab.Prefab_Test_Utils as prefab_test_utils
|
||||
import PrefabTestUtils as prefab_test_utils
|
||||
|
||||
prefab_test_utils.open_base_tests_level()
|
||||
|
||||
# Checks for prefab instantiation passed or not
|
||||
# Instantiates a new car prefab instance
|
||||
test_prefab = Prefab.get_prefab(EXISTING_TEST_PREFAB_FILE_NAME)
|
||||
|
||||
test_instance = test_prefab.instantiate(
|
||||
prefab_position=INSTANTIATED_TEST_PREFAB_POSITION)
|
||||
|
||||
@@ -31,4 +30,4 @@ def Prefab_BasicWorkflow_InstantiatePrefab():
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(Prefab_BasicWorkflow_InstantiatePrefab)
|
||||
Report.start_test(PrefabBasicWorkflow_InstantiatePrefab)
|
||||
+3
-3
@@ -7,9 +7,9 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
# fmt:off
|
||||
class Tests():
|
||||
find_empty_entity = ("Entity: 'EmptyEntity' found", "Entity: 'EmptyEntity' *not* found in level")
|
||||
empty_entity_pos = ("'EmptyEntity' position is at the expected position", "'EmptyEntity' position is *not* at the expected position")
|
||||
find_pxentity = ("Entity: 'EntityWithPxCollider' found", "Entity: 'EntityWithPxCollider' *not* found in level")
|
||||
find_empty_entity = ("Entity: 'EmptyEntity' found", "Entity: 'EmptyEntity' *not* found in level")
|
||||
empty_entity_pos = ("'EmptyEntity' position is at the expected position", "'EmptyEntity' position is *not* at the expected position")
|
||||
find_pxentity = ("Entity: 'EntityWithPxCollider' found", "Entity: 'EntityWithPxCollider' *not* found in level")
|
||||
pxentity_component = ("Entity: 'EntityWithPxCollider' has a Physx Collider", "Entity: 'EntityWithPxCollider' does *not* have a Physx Collider")
|
||||
|
||||
# fmt:on
|
||||
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from azlmbr.entity import EntityId
|
||||
from azlmbr.math import Vector3
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
def check_entity_children_count(entity_id, expected_children_count):
|
||||
entity_children_count_matched_result = (
|
||||
"Entity with a unique name found",
|
||||
"Entity with a unique name *not* found")
|
||||
|
||||
entity = EditorEntity(entity_id)
|
||||
children_entity_ids = entity.get_children_ids()
|
||||
entity_children_count_matched = len(children_entity_ids) == expected_children_count
|
||||
Report.result(entity_children_count_matched_result, entity_children_count_matched)
|
||||
|
||||
if not entity_children_count_matched:
|
||||
Report.info(f"Entity '{entity_id.ToString()}' actual children count: {len(children_entity_ids)}. Expected children count: {expected_children_count}")
|
||||
|
||||
return entity_children_count_matched
|
||||
|
||||
def open_base_tests_level():
|
||||
helper.init_idle()
|
||||
helper.open_level("Prefab", "Base")
|
||||
+1515
File diff suppressed because it is too large
Load Diff
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c3384e88cd0f47ab8ec81eb75101b02ff9675c76dc070c726a9f3f39f1b2b2df
|
||||
size 4994448
|
||||
+160
-38
@@ -1,16 +1,34 @@
|
||||
ProductName: single_mesh_multiple_materials.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
single_mesh_multiple_materials
|
||||
Node Name: Torus
|
||||
Node Path: RootNode.Torus
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Torus_1
|
||||
Node Path: RootNode.Torus.Torus_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 2304. Hash: 12560656679477605282
|
||||
Normals: Count 2304. Hash: 14915939258818888021
|
||||
FaceList: Count 1152. Hash: 3035560221708475304
|
||||
FaceMaterialIds: Count 1152. Hash: 2033667258170256242
|
||||
|
||||
Node Name: Torus_optimized
|
||||
Node Path: RootNode.Torus_optimized
|
||||
Node Name: Torus_2
|
||||
Node Path: RootNode.Torus.Torus_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Torus_1_optimized
|
||||
Node Path: RootNode.Torus.Torus_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 2304. Hash: 12560656679477605282
|
||||
Normals: Count 2304. Hash: 14915939258818888021
|
||||
@@ -18,7 +36,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 1152. Hash: 2033667258170256242
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Torus.transform
|
||||
Node Path: RootNode.Torus.Torus_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -27,13 +45,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Torus.UV0
|
||||
Node Path: RootNode.Torus.Torus_1.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 2304. Hash: 6069930558565069665
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: OrangeMaterial
|
||||
Node Path: RootNode.Torus.OrangeMaterial
|
||||
Node Path: RootNode.Torus.Torus_1.OrangeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: OrangeMaterial
|
||||
UniqueId: 10937477720113828524
|
||||
@@ -63,7 +81,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SecondTextureMaterial
|
||||
Node Path: RootNode.Torus.SecondTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_1.SecondTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondTextureMaterial
|
||||
UniqueId: 16601413836225607467
|
||||
@@ -93,7 +111,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: FirstTextureMaterial
|
||||
Node Path: RootNode.Torus.FirstTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_1.FirstTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: FirstTextureMaterial
|
||||
UniqueId: 2580020563915538382
|
||||
@@ -122,40 +140,21 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Torus.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Torus.Torus_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 2304. Hash: 17641066831235827929
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Torus.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Torus.Torus_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 2304. Hash: 6274616552656695154
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Torus_optimized.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 2304. Hash: 6069930558565069665
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Torus_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 2304. Hash: 17641066831235827929
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Torus_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 2304. Hash: 6274616552656695154
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Torus_optimized.transform
|
||||
Node Path: RootNode.Torus.Torus_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -163,8 +162,14 @@ Node Type: TransformData
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Torus.Torus_2.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 2304. Hash: 6069930558565069665
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: OrangeMaterial
|
||||
Node Path: RootNode.Torus_optimized.OrangeMaterial
|
||||
Node Path: RootNode.Torus.Torus_2.OrangeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: OrangeMaterial
|
||||
UniqueId: 10937477720113828524
|
||||
@@ -194,7 +199,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SecondTextureMaterial
|
||||
Node Path: RootNode.Torus_optimized.SecondTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_2.SecondTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondTextureMaterial
|
||||
UniqueId: 16601413836225607467
|
||||
@@ -224,7 +229,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: FirstTextureMaterial
|
||||
Node Path: RootNode.Torus_optimized.FirstTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_2.FirstTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: FirstTextureMaterial
|
||||
UniqueId: 2580020563915538382
|
||||
@@ -253,3 +258,120 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXTestTexture.png
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 2304. Hash: 6069930558565069665
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 2304. Hash: 17641066831235827929
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 2304. Hash: 6274616552656695154
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: OrangeMaterial
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.OrangeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: OrangeMaterial
|
||||
UniqueId: 10937477720113828524
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.113346, 0.000000>
|
||||
SpecularColor: < 0.800000, 0.113346, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SecondTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.SecondTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondTextureMaterial
|
||||
UniqueId: 16601413836225607467
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: OneMeshMultipleMaterials/FBXSecondTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: FirstTextureMaterial
|
||||
Node Path: RootNode.Torus.Torus_1_optimized.FirstTextureMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: FirstTextureMaterial
|
||||
UniqueId: 2580020563915538382
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: OneMeshMultipleMaterials/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshMultipleMaterials/FBXTestTexture.png
|
||||
|
||||
+97
-34
@@ -1,16 +1,34 @@
|
||||
ProductName: OneMeshOneMaterial.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
OneMeshOneMaterial
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
@@ -18,7 +36,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -27,13 +45,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.UVMap
|
||||
Node Path: RootNode.Cube.Cube_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: CubeMaterial
|
||||
Node Path: RootNode.Cube.CubeMaterial
|
||||
Node Path: RootNode.Cube.Cube_1.CubeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: CubeMaterial
|
||||
UniqueId: 973942033197978066
|
||||
@@ -62,40 +80,21 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -103,8 +102,72 @@ Node Type: TransformData
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: CubeMaterial
|
||||
Node Path: RootNode.Cube_optimized.CubeMaterial
|
||||
Node Path: RootNode.Cube.Cube_2.CubeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: CubeMaterial
|
||||
UniqueId: 973942033197978066
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 36.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: OneMeshOneMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: OneMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: CubeMaterial
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.CubeMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: CubeMaterial
|
||||
UniqueId: 973942033197978066
|
||||
|
||||
+437
-213
@@ -1,64 +1,109 @@
|
||||
ProductName: lodtest.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
lodtest
|
||||
Node Name: lodtest
|
||||
Node Path: RootNode.lodtest
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: lodtest_1
|
||||
Node Path: RootNode.lodtest.lodtest_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: lodtest_lod3
|
||||
Node Path: RootNode.lodtest_lod3
|
||||
Node Name: lodtest_2
|
||||
Node Path: RootNode.lodtest.lodtest_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: lodtest_1_optimized
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: lodtest_lod3_1
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 1984. Hash: 6600975913707260286
|
||||
Normals: Count 1984. Hash: 2708036977889843831
|
||||
FaceList: Count 960. Hash: 10390417165025722786
|
||||
FaceMaterialIds: Count 960. Hash: 12510609185544665964
|
||||
|
||||
Node Name: lodtest_lod2
|
||||
Node Path: RootNode.lodtest_lod2
|
||||
Node Name: lodtest_lod3_2
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 2.298166, 0.000000>
|
||||
|
||||
Node Name: lodtest_lod3_1_optimized
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 1984. Hash: 6600975913707260286
|
||||
Normals: Count 1984. Hash: 2708036977889843831
|
||||
FaceList: Count 960. Hash: 10390417165025722786
|
||||
FaceMaterialIds: Count 960. Hash: 12510609185544665964
|
||||
|
||||
Node Name: lodtest_lod2_1
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 240. Hash: 219362421205407416
|
||||
Normals: Count 240. Hash: 11195242321181199939
|
||||
FaceList: Count 80. Hash: 11130917988116538993
|
||||
FaceMaterialIds: Count 80. Hash: 4190892684086530065
|
||||
|
||||
Node Name: lodtest_lod1
|
||||
Node Path: RootNode.lodtest_lod1
|
||||
Node Name: lodtest_lod2_2
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, -0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, -2.211498, 0.000000>
|
||||
|
||||
Node Name: lodtest_lod2_1_optimized
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 240. Hash: 219362421205407416
|
||||
Normals: Count 240. Hash: 11195242321181199939
|
||||
FaceList: Count 80. Hash: 11130917988116538993
|
||||
FaceMaterialIds: Count 80. Hash: 4190892684086530065
|
||||
|
||||
Node Name: lodtest_lod1_1
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 1283526254311745349
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
FaceList: Count 124. Hash: 3728991722746136013
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: lodtest_optimized
|
||||
Node Path: RootNode.lodtest_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
Node Name: lodtest_lod1_2
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 2.410331, 0.000000, 0.000000>
|
||||
|
||||
Node Name: lodtest_lod3_optimized
|
||||
Node Path: RootNode.lodtest_lod3_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 1984. Hash: 6600975913707260286
|
||||
Normals: Count 1984. Hash: 2708036977889843831
|
||||
FaceList: Count 960. Hash: 10390417165025722786
|
||||
FaceMaterialIds: Count 960. Hash: 12510609185544665964
|
||||
|
||||
Node Name: lodtest_lod2_optimized
|
||||
Node Path: RootNode.lodtest_lod2_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 240. Hash: 219362421205407416
|
||||
Normals: Count 240. Hash: 11195242321181199939
|
||||
FaceList: Count 80. Hash: 11130917988116538993
|
||||
FaceMaterialIds: Count 80. Hash: 4190892684086530065
|
||||
|
||||
Node Name: lodtest_lod1_optimized
|
||||
Node Path: RootNode.lodtest_lod1_optimized
|
||||
Node Name: lodtest_lod1_1_optimized
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 7921557352486854444
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
@@ -66,7 +111,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest.transform
|
||||
Node Path: RootNode.lodtest.lodtest_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -75,13 +120,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest.UVMap
|
||||
Node Path: RootNode.lodtest.lodtest_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.lodtest.Material
|
||||
Node Path: RootNode.lodtest.lodtest_1.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
@@ -110,21 +155,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest.lodtest_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest.lodtest_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod3.transform
|
||||
Node Path: RootNode.lodtest.lodtest_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest.lodtest_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.lodtest.lodtest_2.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 36.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.lodtest.lodtest_1_optimized.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 36.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -133,13 +281,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 2.298166, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod3.UVMap
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 1984. Hash: 14119273880200542497
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod3.DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -168,21 +316,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod3.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 1984. Hash: 5664494957869921957
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod3.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 1984. Hash: 5048878728906162461
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod2.transform
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 2.298166, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 1984. Hash: 14119273880200542497
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_2.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 1984. Hash: 14119273880200542497
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 1984. Hash: 5664494957869921957
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 1984. Hash: 5048878728906162461
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 2.298166, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod3.lodtest_lod3_1_optimized.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, -0.000000, 0.000000>
|
||||
@@ -191,13 +442,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, -2.211498, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod2.UVMap
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 240. Hash: 13702273589593616598
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod2.DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -226,21 +477,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod2.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 240. Hash: 1390901212717410749
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod2.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 240. Hash: 1379238632949267281
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod1.transform
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, -0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, -2.211498, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 240. Hash: 13702273589593616598
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_2.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 240. Hash: 13702273589593616598
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 240. Hash: 1390901212717410749
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 240. Hash: 1379238632949267281
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, -0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, -2.211498, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod2.lodtest_lod2_1_optimized.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -249,13 +603,13 @@ Node Type: TransformData
|
||||
Transl: < 2.410331, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod1.UVMap
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod1.DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -284,107 +638,36 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod1.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 11165448242141781141
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod1.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 7987814487334449536
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_optimized.transform
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.lodtest_optimized.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 36.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
Transl: < 2.410331, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod3_optimized.UVMap
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 1984. Hash: 14119273880200542497
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod3_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 1984. Hash: 5664494957869921957
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod3_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 1984. Hash: 5048878728906162461
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod3_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 2.298166, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod3_optimized.DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_2.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -414,84 +697,26 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod2_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 240. Hash: 13702273589593616598
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod2_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 240. Hash: 1390901212717410749
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod2_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 240. Hash: 1379238632949267281
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod2_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, -0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, -2.211498, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod2_optimized.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.lodtest_lod1_optimized.UVMap
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 13790301632763350589
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod1_optimized.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 7293001660047850407
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.lodtest_lod1_optimized.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 2874689498270494796
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.lodtest_lod1_optimized.transform
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -500,7 +725,7 @@ Node Type: TransformData
|
||||
Transl: < 2.410331, 0.000000, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod1_optimized.DefaultMaterial
|
||||
Node Path: RootNode.lodtest_lod1.lodtest_lod1_1_optimized.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -528,4 +753,3 @@ Node Type: MaterialData
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
|
||||
+167
-51
@@ -1,32 +1,59 @@
|
||||
ProductName: physicstest.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
physicstest
|
||||
Node Name: Cone
|
||||
Node Path: RootNode.Cone
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cone_1
|
||||
Node Path: RootNode.Cone.Cone_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 128. Hash: 7714223793259938211
|
||||
Normals: Count 128. Hash: 2352668179264002707
|
||||
FaceList: Count 62. Hash: 14563017593520122982
|
||||
FaceMaterialIds: Count 62. Hash: 12234218120113875284
|
||||
|
||||
Node Name: Cube_phys
|
||||
Node Path: RootNode.Cube_phys
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 3478903613105670818
|
||||
Normals: Count 24. Hash: 7251512570672401149
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
Node Name: Cone_2
|
||||
Node Path: RootNode.Cone.Cone_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cone_optimized
|
||||
Node Path: RootNode.Cone_optimized
|
||||
Node Name: Cone_1_optimized
|
||||
Node Path: RootNode.Cone.Cone_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 128. Hash: 10174710861731544050
|
||||
Normals: Count 128. Hash: 2352668179264002707
|
||||
FaceList: Count 62. Hash: 11332459830831720586
|
||||
FaceMaterialIds: Count 62. Hash: 12234218120113875284
|
||||
|
||||
Node Name: Cube_phys_1
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 3478903613105670818
|
||||
Normals: Count 24. Hash: 7251512570672401149
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cube_phys_2
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone.transform
|
||||
Node Path: RootNode.Cone.Cone_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -35,13 +62,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cone.UVMap
|
||||
Node Path: RootNode.Cone.Cone_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 10171083346831193808
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.Cone.DefaultMaterial
|
||||
Node Path: RootNode.Cone.Cone_1.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -70,21 +97,21 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 128. Hash: 14351734474754285313
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 128. Hash: 15997251922861304891
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_phys.transform
|
||||
Node Path: RootNode.Cone.Cone_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -93,13 +120,116 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_phys.UVMap
|
||||
Node Path: RootNode.Cone.Cone_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 10171083346831193808
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.Cone.Cone_2.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 7873368003484215433
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 128. Hash: 12937806066914201637
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 128. Hash: 873786942732834087
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 0.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 13623018071435219250
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.Cube_phys.DefaultMaterial
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -128,40 +258,21 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_phys.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 11965897353301448436
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_phys.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 17515781720544086759
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cone_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 7873368003484215433
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 128. Hash: 12937806066914201637
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 128. Hash: 873786942732834087
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone_optimized.transform
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -169,8 +280,14 @@ Node Type: TransformData
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 13623018071435219250
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: DefaultMaterial
|
||||
Node Path: RootNode.Cone_optimized.DefaultMaterial
|
||||
Node Path: RootNode.Cube_phys.Cube_phys_2.DefaultMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: DefaultMaterial
|
||||
UniqueId: 3809502407269006983
|
||||
@@ -198,4 +315,3 @@ Node Type: MaterialData
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
|
||||
+271
-95
@@ -1,32 +1,59 @@
|
||||
ProductName: multiple_mesh_linked_materials.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
multiple_mesh_linked_materials
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7113802799051126666
|
||||
|
||||
Node Name: Cone
|
||||
Node Path: RootNode.Cone
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7113802799051126666
|
||||
|
||||
Node Name: Cone_1
|
||||
Node Path: RootNode.Cone.Cone_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 128. Hash: 12506421592104186200
|
||||
Normals: Count 128. Hash: 367461522682321485
|
||||
FaceList: Count 62. Hash: 13208951979626973193
|
||||
FaceMaterialIds: Count 62. Hash: 15454348664434923102
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7113802799051126666
|
||||
Node Name: Cone_2
|
||||
Node Path: RootNode.Cone.Cone_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 2.000000>
|
||||
|
||||
Node Name: Cone_optimized
|
||||
Node Path: RootNode.Cone_optimized
|
||||
Node Name: Cone_1_optimized
|
||||
Node Path: RootNode.Cone.Cone_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 128. Hash: 14946490408303214595
|
||||
Normals: Count 128. Hash: 367461522682321485
|
||||
@@ -34,7 +61,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 62. Hash: 15454348664434923102
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -43,13 +70,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cube.UV0
|
||||
Node Path: RootNode.Cube.Cube_1.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cube.SharedBlack
|
||||
Node Path: RootNode.Cube.Cube_1.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
@@ -79,7 +106,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cube.SharedOrange
|
||||
Node Path: RootNode.Cube.Cube_1.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
@@ -108,21 +135,184 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cube.Cube_2.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cube.Cube_2.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.000000, 0.000000, 0.000000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cube.Cube_2.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.139382, 0.014429>
|
||||
SpecularColor: < 0.800000, 0.139382, 0.014429>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.000000, 0.000000, 0.000000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.139382, 0.014429>
|
||||
SpecularColor: < 0.800000, 0.139382, 0.014429>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone.Cone_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -131,13 +321,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 2.000000>
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cone.UV0
|
||||
Node Path: RootNode.Cone.Cone_1.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 10291654057525777310
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cone.SharedOrange
|
||||
Node Path: RootNode.Cone.Cone_1.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
@@ -167,7 +357,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cone.SharedBlack
|
||||
Node Path: RootNode.Cone.Cone_1.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
@@ -196,79 +386,36 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 128. Hash: 12695232913942738512
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 128. Hash: 9034210764777745751
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cube_optimized.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cone.Cone_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
Transl: < 0.000000, 0.000000, 2.000000>
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cube_optimized.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.000000, 0.000000, 0.000000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cone.Cone_2.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 10291654057525777310
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cube_optimized.SharedOrange
|
||||
Node Path: RootNode.Cone.Cone_2.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
@@ -297,27 +444,57 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cone.Cone_2.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.000000, 0.000000, 0.000000>
|
||||
SpecularColor: < 0.000000, 0.000000, 0.000000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UV0
|
||||
Node Path: RootNode.Cone_optimized.UV0
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.UV0
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 128. Hash: 7173974213247584731
|
||||
UVCustomName: UV0
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone_optimized.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 128. Hash: 10740776669168782230
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cone_optimized.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 128. Hash: 6990068477421150065
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cone_optimized.transform
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -326,7 +503,7 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 2.000000>
|
||||
|
||||
Node Name: SharedOrange
|
||||
Node Path: RootNode.Cone_optimized.SharedOrange
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.SharedOrange
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedOrange
|
||||
UniqueId: 9470651048605569128
|
||||
@@ -356,7 +533,7 @@ Node Type: MaterialData
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: SharedBlack
|
||||
Node Path: RootNode.Cone_optimized.SharedBlack
|
||||
Node Path: RootNode.Cone.Cone_1_optimized.SharedBlack
|
||||
Node Type: MaterialData
|
||||
MaterialName: SharedBlack
|
||||
UniqueId: 5248829540156873090
|
||||
@@ -384,4 +561,3 @@ Node Type: MaterialData
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
|
||||
+179
-63
@@ -1,32 +1,59 @@
|
||||
ProductName: multiple_mesh_one_material.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
multiple_mesh_one_material
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder
|
||||
Node Path: RootNode.Cylinder
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder_1
|
||||
Node Path: RootNode.Cylinder.Cylinder_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 1283526254311745349
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
FaceList: Count 124. Hash: 3728991722746136013
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
Node Name: Cylinder_2
|
||||
Node Path: RootNode.Cylinder.Cylinder_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cylinder_optimized
|
||||
Node Path: RootNode.Cylinder_optimized
|
||||
Node Name: Cylinder_1_optimized
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 7921557352486854444
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
@@ -34,7 +61,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -43,13 +70,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.UVMap
|
||||
Node Path: RootNode.Cube.Cube_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -78,21 +105,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_2.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -101,13 +231,13 @@ Node Type: TransformData
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cylinder.SingleMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -136,49 +266,36 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 11165448242141781141
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 7987814487334449536
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube_optimized.SingleMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -208,26 +325,26 @@ Node Type: MaterialData
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder_optimized.UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 13790301632763350589
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder_optimized.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 7293001660047850407
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder_optimized.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 2874689498270494796
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder_optimized.transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -236,7 +353,7 @@ Node Type: TransformData
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cylinder_optimized.SingleMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -264,4 +381,3 @@ Node Type: MaterialData
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshOneMaterial/FBXTestTexture.png
|
||||
|
||||
|
||||
+186
-70
@@ -1,32 +1,59 @@
|
||||
ProductName: multiple_mesh_multiple_material.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
multiple_mesh_multiple_material
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder
|
||||
Node Path: RootNode.Cylinder
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder_1
|
||||
Node Path: RootNode.Cylinder.Cylinder_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 1283526254311745349
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
FaceList: Count 124. Hash: 3728991722746136013
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
Node Name: Cylinder_2
|
||||
Node Path: RootNode.Cylinder.Cylinder_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cylinder_optimized
|
||||
Node Path: RootNode.Cylinder_optimized
|
||||
Node Name: Cylinder_1_optimized
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 7921557352486854444
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
@@ -34,7 +61,7 @@ Node Type: MeshData
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -43,13 +70,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.UVMap
|
||||
Node Path: RootNode.Cube.Cube_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -78,21 +105,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_2.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -101,13 +231,13 @@ Node Type: TransformData
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SecondMaterial
|
||||
Node Path: RootNode.Cylinder.SecondMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.SecondMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondMaterial
|
||||
UniqueId: 5229255358802505087
|
||||
@@ -136,55 +266,42 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 11165448242141781141
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 7987814487334449536
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube_optimized.SingleMaterial
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SecondMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.SecondMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
MaterialName: SecondMaterial
|
||||
UniqueId: 5229255358802505087
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
@@ -197,7 +314,7 @@ Node Type: MaterialData
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
@@ -205,29 +322,29 @@ Node Type: MaterialData
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder_optimized.UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 13790301632763350589
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder_optimized.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 7293001660047850407
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder_optimized.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 2874689498270494796
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder_optimized.transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -236,7 +353,7 @@ Node Type: TransformData
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SecondMaterial
|
||||
Node Path: RootNode.Cylinder_optimized.SecondMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_1_optimized.SecondMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondMaterial
|
||||
UniqueId: 5229255358802505087
|
||||
@@ -264,4 +381,3 @@ Node Type: MaterialData
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
|
||||
|
||||
+175
-59
@@ -1,32 +1,59 @@
|
||||
ProductName: multiple_mesh_multiple_material.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
multiple_mesh_multiple_material
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder
|
||||
Node Path: RootNode.Cylinder
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
|
||||
Node Name: Cylinder_1
|
||||
Node Path: RootNode.Cylinder.Cylinder_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 192. Hash: 1283526254311745349
|
||||
Normals: Count 192. Hash: 1873340970602844856
|
||||
FaceList: Count 124. Hash: 3728991722746136013
|
||||
FaceMaterialIds: Count 124. Hash: 2372486708814455910
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24. Hash: 8661923109306356285
|
||||
Normals: Count 24. Hash: 5807525742165000561
|
||||
FaceList: Count 12. Hash: 9888799799190757436
|
||||
FaceMaterialIds: Count 12. Hash: 7110546404675862471
|
||||
Node Name: Cylinder_2
|
||||
Node Path: RootNode.Cylinder.Cylinder_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -35,13 +62,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.UVMap
|
||||
Node Path: RootNode.Cube.Cube_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
@@ -70,21 +97,124 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_2.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.SingleMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -93,13 +223,13 @@ Node Type: TransformData
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SecondMaterial
|
||||
Node Path: RootNode.Cylinder.SecondMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.SecondMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SecondMaterial
|
||||
UniqueId: 5229255358802505087
|
||||
@@ -128,55 +258,42 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 192. Hash: 11165448242141781141
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cylinder.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cylinder.Cylinder_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 192. Hash: 7987814487334449536
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24. Hash: 1622169145591646736
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24. Hash: 13438447437797057049
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24. Hash: 11372562338897179017
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
Transl: <-4.388482, 0.000000, 0.000000>
|
||||
|
||||
Node Name: SingleMaterial
|
||||
Node Path: RootNode.Cube_optimized.SingleMaterial
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 192. Hash: 27253578623892681
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: SecondMaterial
|
||||
Node Path: RootNode.Cylinder.Cylinder_2.SecondMaterial
|
||||
Node Type: MaterialData
|
||||
MaterialName: SingleMaterial
|
||||
UniqueId: 14432700632681398127
|
||||
MaterialName: SecondMaterial
|
||||
UniqueId: 5229255358802505087
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.814049, 0.814049, 0.814049>
|
||||
SpecularColor: < 0.814049, 0.814049, 0.814049>
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 25.000000
|
||||
@@ -189,7 +306,7 @@ Node Type: MaterialData
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
DiffuseTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
@@ -197,5 +314,4 @@ Node Type: MaterialData
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXTestTexture.png
|
||||
|
||||
BaseColorTexture: TwoMeshTwoMaterial/FBXSecondTestTexture.png
|
||||
|
||||
+107
-39
@@ -1,30 +1,48 @@
|
||||
ProductName: vertexcolor.dbgsg
|
||||
debugSceneGraphVersion: 1
|
||||
vertexcolor
|
||||
Node Name: Cube
|
||||
Node Path: RootNode.Cube
|
||||
Node Name: RootNode
|
||||
Node Path: RootNode
|
||||
Node Type: RootBoneData
|
||||
WorldTransform:
|
||||
BasisX: < 1.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, 1.000000, 0.000000>
|
||||
BasisZ: < 0.000000, 0.000000, 1.000000>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1
|
||||
Node Path: RootNode.Cube.Cube_1
|
||||
Node Type: MeshData
|
||||
Positions: Count 24576. Hash: 7031773714680283213
|
||||
Normals: Count 24576. Hash: 8968157737282745201
|
||||
FaceList: Count 12288. Hash: 13183441914179219962
|
||||
FaceMaterialIds: Count 12288. Hash: 12545154121625736090
|
||||
|
||||
Node Name: Cube_optimized
|
||||
Node Path: RootNode.Cube_optimized
|
||||
Node Name: Cube_2
|
||||
Node Path: RootNode.Cube.Cube_2
|
||||
Node Type: BoneData
|
||||
WorldTransform:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Cube_1_optimized
|
||||
Node Path: RootNode.Cube.Cube_1_optimized
|
||||
Node Type: MeshData
|
||||
Positions: Count 24576. Hash: 7031773714680283213
|
||||
Normals: Count 24576. Hash: 8968157737282745201
|
||||
FaceList: Count 12288. Hash: 13183441914179219962
|
||||
Positions: Count 6376. Hash: 10806296444120211070
|
||||
Normals: Count 6376. Hash: 3814626075063770280
|
||||
FaceList: Count 12288. Hash: 15242182080304859208
|
||||
FaceMaterialIds: Count 12288. Hash: 12545154121625736090
|
||||
|
||||
Node Name: Col0
|
||||
Node Path: RootNode.Cube.Col0
|
||||
Node Path: RootNode.Cube.Cube_1.Col0
|
||||
Node Type: MeshVertexColorData
|
||||
Colors: Count 24576. Hash: 17169952715183318502
|
||||
ColorsCustomName:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.transform
|
||||
Node Path: RootNode.Cube.Cube_1.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -33,13 +51,13 @@ Node Type: TransformData
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.UVMap
|
||||
Node Path: RootNode.Cube.Cube_1.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24576. Hash: 4554678369329207802
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.Cube.Material
|
||||
Node Path: RootNode.Cube.Cube_1.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
@@ -68,46 +86,27 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.TangentSet_MikkT_0
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24576. Hash: 13321090379606717973
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube.BitangentSet_MikkT_0
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24576. Hash: 17217515414004886507
|
||||
TangentSpace: 1
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24576. Hash: 4554678369329207802
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.TangentSet_MikkT_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 24576. Hash: 13321090379606717973
|
||||
TangentSpace: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_MikkT_0
|
||||
Node Path: RootNode.Cube_optimized.BitangentSet_MikkT_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 24576. Hash: 17217515414004886507
|
||||
TangentSpace: 1
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: Col0
|
||||
Node Path: RootNode.Cube_optimized.Col0
|
||||
Node Path: RootNode.Cube.Cube_2.Col0
|
||||
Node Type: MeshVertexColorData
|
||||
Colors: Count 24576. Hash: 17169952715183318502
|
||||
ColorsCustomName:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube_optimized.transform
|
||||
Node Path: RootNode.Cube.Cube_2.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
@@ -115,8 +114,14 @@ Node Type: TransformData
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_2.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 24576. Hash: 4554678369329207802
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.Cube_optimized.Material
|
||||
Node Path: RootNode.Cube.Cube_2.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
@@ -145,3 +150,66 @@ Node Type: MaterialData
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
Node Name: UVMap
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.UVMap
|
||||
Node Type: MeshVertexUVData
|
||||
UVs: Count 6376. Hash: 12957930967905951851
|
||||
UVCustomName: UVMap
|
||||
|
||||
Node Name: TangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.TangentSet_0
|
||||
Node Type: MeshVertexTangentData
|
||||
Tangents: Count 6376. Hash: 7712841033379094373
|
||||
GenerationMethod: 1
|
||||
SetIndex: 0
|
||||
|
||||
Node Name: BitangentSet_0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.BitangentSet_0
|
||||
Node Type: MeshVertexBitangentData
|
||||
Bitangents: Count 6376. Hash: 12547048737213169362
|
||||
GenerationMethod: 1
|
||||
|
||||
Node Name: Col0
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.Col0
|
||||
Node Type: MeshVertexColorData
|
||||
Colors: Count 6376. Hash: 8761962599807935159
|
||||
ColorsCustomName:
|
||||
|
||||
Node Name: transform
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.transform
|
||||
Node Type: TransformData
|
||||
Matrix:
|
||||
BasisX: < 100.000000, 0.000000, 0.000000>
|
||||
BasisY: < 0.000000, -0.000016, 100.000000>
|
||||
BasisZ: < 0.000000, -100.000000, -0.000016>
|
||||
Transl: < 0.000000, 0.000000, 0.000000>
|
||||
|
||||
Node Name: Material
|
||||
Node Path: RootNode.Cube.Cube_1_optimized.Material
|
||||
Node Type: MaterialData
|
||||
MaterialName: Material
|
||||
UniqueId: 11127505492038345244
|
||||
IsNoDraw: false
|
||||
DiffuseColor: < 0.800000, 0.800000, 0.800000>
|
||||
SpecularColor: < 0.800000, 0.800000, 0.800000>
|
||||
EmissiveColor: < 0.000000, 0.000000, 0.000000>
|
||||
Opacity: 1.000000
|
||||
Shininess: 36.000000
|
||||
UseColorMap: Not set
|
||||
BaseColor: Not set
|
||||
UseMetallicMap: Not set
|
||||
MetallicFactor: Not set
|
||||
UseRoughnessMap: Not set
|
||||
RoughnessFactor: Not set
|
||||
UseEmissiveMap: Not set
|
||||
EmissiveIntensity: Not set
|
||||
UseAOMap: Not set
|
||||
DiffuseTexture:
|
||||
SpecularTexture:
|
||||
BumpTexture:
|
||||
NormalTexture:
|
||||
MetallicTexture:
|
||||
RoughnessTexture:
|
||||
AmbientOcclusionTexture:
|
||||
EmissiveTexture:
|
||||
BaseColorTexture:
|
||||
|
||||
@@ -67,7 +67,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=1,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='onemeshonematerial/onemeshonematerial.dbgsg',
|
||||
@@ -99,7 +99,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=9,
|
||||
warning_count=22,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='softnaminglod/lodtest.dbgsg',
|
||||
@@ -131,7 +131,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=6,
|
||||
warning_count=14,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='softnamingphysics/physicstest.dbgsg',
|
||||
@@ -165,7 +165,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=2,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='twomeshonematerial/multiple_mesh_one_material.dbgsg',
|
||||
@@ -197,7 +197,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=2,
|
||||
products= [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='twomeshlinkedmaterials/multiple_mesh_linked_materials.dbgsg',
|
||||
@@ -230,7 +230,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=1,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='onemeshmultiplematerials/single_mesh_multiple_materials.dbgsg',
|
||||
@@ -260,7 +260,7 @@ blackbox_fbx_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=1,
|
||||
products=[
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='vertexcolor/vertexcolor.dbgsg',
|
||||
@@ -275,6 +275,38 @@ blackbox_fbx_tests = [
|
||||
id="35796285",
|
||||
marks=pytest.mark.test_case_id("C35796285"),
|
||||
),
|
||||
pytest.param(
|
||||
BlackboxAssetTest(
|
||||
test_name= "MotionTest_RunAP_SuccessWithMatchingProducts",
|
||||
asset_folder= "Motion",
|
||||
scene_debug_file="Jack_Idle_Aim_ZUp.dbgsg",
|
||||
assets = [
|
||||
asset_db_utils.DBSourceAsset(
|
||||
source_file_name = "Jack_Idle_Aim_ZUp.fbx",
|
||||
uuid = b"eda904ae0e145f8b973d57fc5809918b",
|
||||
jobs = [
|
||||
asset_db_utils.DBJob(
|
||||
job_key= "Scene compilation",
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='motion/jack_idle_aim_zup.dbgsg',
|
||||
sub_id=-517610290,
|
||||
asset_type=b'07f289d14dc74c4094b40a53bbcb9f0b'),
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='motion/jack_idle_aim_zup.motion',
|
||||
sub_id=186392073,
|
||||
asset_type=b'00494b8e75784ba28b28272e90680787')
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -296,7 +328,7 @@ blackbox_fbx_special_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=2,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='twomeshtwomaterial/multiple_mesh_multiple_material.dbgsg',
|
||||
@@ -317,7 +349,7 @@ blackbox_fbx_special_tests = [
|
||||
builder_guid=b"bd8bf65894854fe3830e8ec3a23c35f3",
|
||||
status=4,
|
||||
error_count=0,
|
||||
warning_count=0,
|
||||
warning_count=2,
|
||||
products = [
|
||||
asset_db_utils.DBProduct(
|
||||
product_name='twomeshtwomaterial/multiple_mesh_multiple_material.dbgsg',
|
||||
@@ -387,7 +419,6 @@ class TestsFBX_AllPlatforms(object):
|
||||
self.run_fbx_test(workspace, ap_setup_fixture,
|
||||
asset_processor, project, blackbox_param, True)
|
||||
|
||||
|
||||
def populateAssetInfo(self, workspace, project, assets):
|
||||
|
||||
# Check that each given source asset resulted in the expected jobs and products.
|
||||
@@ -398,7 +429,6 @@ class TestsFBX_AllPlatforms(object):
|
||||
product.product_name = job.platform + "/" \
|
||||
+ product.product_name
|
||||
|
||||
|
||||
def run_fbx_test(self, workspace, ap_setup_fixture, asset_processor,
|
||||
project, blackbox_params: BlackboxAssetTest, overrideAsset = False):
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
# This timeouts on jenkins, investigation is needed. Commment for now
|
||||
#
|
||||
#if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
# ly_add_pytest(
|
||||
# NAME AutomatedTesting::EditorTestTesting
|
||||
# TEST_SUITE main
|
||||
# TEST_SERIAL
|
||||
# PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py
|
||||
# RUNTIME_DEPENDENCIES
|
||||
# Legacy::Editor
|
||||
# AZ::AssetProcessor
|
||||
# AutomatedTesting.Assets
|
||||
# COMPONENT
|
||||
# TestTools
|
||||
# )
|
||||
#endif()
|
||||
@@ -35,10 +35,11 @@ class TestEditorTest:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
TestEditorTest.args = sys.argv.copy()
|
||||
build_dir_arg_index = TestEditorTest.args.index("--build-directory")
|
||||
if build_dir_arg_index < 0:
|
||||
print("Error: Must pass --build-directory argument in order to run this test")
|
||||
sys.exit(-2)
|
||||
build_dir_arg_index = -1
|
||||
try:
|
||||
build_dir_arg_index = TestEditorTest.args.index("--build-directory")
|
||||
except ValueError as ex:
|
||||
raise ValueError("Must pass --build-directory argument in order to run this test")
|
||||
|
||||
TestEditorTest.args[build_dir_arg_index+1] = os.path.abspath(TestEditorTest.args[build_dir_arg_index+1])
|
||||
TestEditorTest.args.append("-s")
|
||||
|
||||
+3
@@ -9,6 +9,7 @@ import os
|
||||
import pytest
|
||||
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools._internal.pytest_plugin as internal_plugin
|
||||
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite
|
||||
|
||||
|
||||
@@ -79,6 +80,8 @@ class TestAutomation(EditorTestSuite):
|
||||
class test_LandscapeCanvas_GradientNodes_EntityRemovedOnNodeDelete(EditorSharedTest):
|
||||
from .EditorScripts import GradientNodes_EntityRemovedOnNodeDelete as test_module
|
||||
|
||||
@pytest.mark.skipif("debug" == os.path.basename(internal_plugin.build_directory),
|
||||
reason="https://github.com/o3de/o3de/issues/4872")
|
||||
class test_LandscapeCanvas_GraphUpdates_UpdateComponents(EditorSharedTest):
|
||||
from .EditorScripts import GraphUpdates_UpdateComponents as test_module
|
||||
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from collections import Counter
|
||||
from collections import deque
|
||||
from os import path
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
|
||||
from azlmbr.entity import EntityId
|
||||
from azlmbr.math import Vector3
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.prefab as prefab
|
||||
import editor_python_test_tools.pyside_utils as pyside_utils
|
||||
import prefab.Prefab_Test_Utils as prefab_test_utils
|
||||
|
||||
# This is a helper class which contains some of the useful information about a prefab instance.
|
||||
class PrefabInstance:
|
||||
|
||||
def __init__(self, prefab_file_name: str=None, container_entity: EditorEntity=EntityId()):
|
||||
self.prefab_file_name: str = prefab_file_name
|
||||
self.container_entity: EditorEntity = container_entity
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.container_entity.id == other.container_entity.id
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.container_entity.id)
|
||||
|
||||
"""
|
||||
See if this instance is valid to be used with other prefab operations.
|
||||
:return: Whether the target instance is valid or not.
|
||||
"""
|
||||
def is_valid() -> bool:
|
||||
return self.container_entity.id.IsValid() and self.prefab_file_name in Prefab.existing_prefabs
|
||||
|
||||
"""
|
||||
Reparent this instance to target parent entity.
|
||||
The function will also check pop up dialog ui in editor to see if there's prefab cyclical dependency error while reparenting prefabs.
|
||||
:param parent_entity_id: The id of the entity this instance should be a child of in the transform hierarchy next.
|
||||
"""
|
||||
async def ui_reparent_prefab_instance(self, parent_entity_id: EntityId):
|
||||
container_entity_id_before_reparent = self.container_entity.id
|
||||
|
||||
original_parent = EditorEntity(self.container_entity.get_parent_id())
|
||||
original_parent_before_reparent_children_ids = set(original_parent.get_children_ids())
|
||||
|
||||
new_parent = EditorEntity(parent_entity_id)
|
||||
new_parent_before_reparent_children_ids = set(new_parent.get_children_ids())
|
||||
|
||||
pyside_utils.run_soon(lambda: self.container_entity.set_parent_entity(parent_entity_id))
|
||||
pyside_utils.run_soon(lambda: prefab_test_utils.wait_for_propagation())
|
||||
|
||||
try:
|
||||
active_modal_widget = await pyside_utils.wait_for_modal_widget()
|
||||
error_message_box = active_modal_widget.findChild(QtWidgets.QMessageBox)
|
||||
ok_button = error_message_box.button(QtWidgets.QMessageBox.Ok)
|
||||
ok_button.click()
|
||||
assert False, "Cyclical dependency detected while reparenting prefab"
|
||||
except pyside_utils.EventLoopTimeoutException:
|
||||
pass
|
||||
|
||||
original_parent_after_reparent_children_ids = set(original_parent.get_children_ids())
|
||||
assert len(original_parent_after_reparent_children_ids) == len(original_parent_before_reparent_children_ids) - 1, \
|
||||
"The children count of the Prefab Instance's original parent should be decreased by 1."
|
||||
assert not container_entity_id_before_reparent in original_parent_after_reparent_children_ids, \
|
||||
"This Prefab Instance is still a child entity of its original parent entity."
|
||||
|
||||
new_parent_after_reparent_children_ids = set(new_parent.get_children_ids())
|
||||
assert len(new_parent_after_reparent_children_ids) == len(new_parent_before_reparent_children_ids) + 1, \
|
||||
"The children count of the Prefab Instance's new parent should be increased by 1."
|
||||
|
||||
container_entity_id_after_reparent = set(new_parent_after_reparent_children_ids).difference(new_parent_before_reparent_children_ids).pop()
|
||||
reparented_container_entity = EditorEntity(container_entity_id_after_reparent)
|
||||
reparented_container_entity_parent_id = reparented_container_entity.get_parent_id()
|
||||
has_correct_parent = reparented_container_entity_parent_id.ToString() == parent_entity_id.ToString()
|
||||
assert has_correct_parent, "Prefab Instance reparented is *not* under the expected parent entity"
|
||||
|
||||
self.container_entity = reparented_container_entity
|
||||
|
||||
# This is a helper class which contains some of the useful information about a prefab template.
|
||||
class Prefab:
|
||||
|
||||
existing_prefabs = {}
|
||||
|
||||
def __init__(self, file_name: str):
|
||||
self.file_name:str = file_name
|
||||
self.file_path: str = prefab_test_utils.get_prefab_file_path(file_name)
|
||||
self.instances: set[PrefabInstance] = set()
|
||||
|
||||
"""
|
||||
Check if a prefab is ready to be used to generate its instances.
|
||||
:param file_name: A unique file name of the target prefab.
|
||||
:return: Whether the target prefab is loaded or not.
|
||||
"""
|
||||
@classmethod
|
||||
def is_prefab_loaded(cls, file_name: str) -> bool:
|
||||
return file_name in Prefab.existing_prefabs
|
||||
|
||||
"""
|
||||
Check if a prefab exists in the directory for files of prefab tests.
|
||||
:param file_name: A unique file name of the target prefab.
|
||||
:return: Whether the target prefab exists or not.
|
||||
"""
|
||||
@classmethod
|
||||
def prefab_exists(cls, file_name: str) -> bool:
|
||||
file_path = prefab_test_utils.get_prefab_file_path(file_name)
|
||||
return path.exists(file_path)
|
||||
|
||||
"""
|
||||
Return a prefab which can be used immediately.
|
||||
:param file_name: A unique file name of the target prefab.
|
||||
:return: The prefab with given file name.
|
||||
"""
|
||||
@classmethod
|
||||
def get_prefab(cls, file_name: str) -> Prefab:
|
||||
if Prefab.is_prefab_loaded(file_name):
|
||||
return Prefab.existing_prefabs[file_name]
|
||||
else:
|
||||
assert Prefab.prefab_exists(file_name), f"Attempted to get a prefab {file_name} that doesn't exist"
|
||||
new_prefab = Prefab(file_name)
|
||||
Prefab.existing_prefabs[file_name] = Prefab(file_name)
|
||||
return new_prefab
|
||||
|
||||
"""
|
||||
Create a prefab in memory and return it. The very first instance of this prefab will also be created.
|
||||
:param entities: The entities that should form the new prefab (along with their descendants).
|
||||
:param file_name: A unique file name of new prefab.
|
||||
:param prefab_instance_name: A name for the very first instance generated while prefab creation. The default instance name is the same as file_name.
|
||||
:return: Created Prefab object and the very first PrefabInstance object owned by the prefab.
|
||||
"""
|
||||
@classmethod
|
||||
def create_prefab(cls, entities: list[EditorEntity], file_name: str, prefab_instance_name: str=None) -> (Prefab, PrefabInstance):
|
||||
assert not Prefab.is_prefab_loaded(file_name), f"Can't create Prefab '{file_name}' since the prefab already exists"
|
||||
|
||||
new_prefab = Prefab(file_name)
|
||||
entity_ids = [entity.id for entity in entities]
|
||||
create_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'CreatePrefabInMemory', entity_ids, new_prefab.file_path)
|
||||
assert create_prefab_result.IsSuccess(), f"Prefab operation 'CreatePrefab' failed. Error: {create_prefab_result.GetError()}"
|
||||
|
||||
container_entity_id = create_prefab_result.GetValue()
|
||||
container_entity = EditorEntity(container_entity_id)
|
||||
|
||||
if prefab_instance_name:
|
||||
container_entity.set_name(prefab_instance_name)
|
||||
|
||||
prefab_test_utils.wait_for_propagation()
|
||||
|
||||
new_prefab_instance = PrefabInstance(file_name, EditorEntity(container_entity_id))
|
||||
new_prefab.instances.add(new_prefab_instance)
|
||||
Prefab.existing_prefabs[file_name] = new_prefab
|
||||
return new_prefab, new_prefab_instance
|
||||
|
||||
"""
|
||||
Remove target prefab instances.
|
||||
:param prefab_instances: Instances to be removed.
|
||||
"""
|
||||
@classmethod
|
||||
def remove_prefabs(cls, prefab_instances: list[PrefabInstance]):
|
||||
entity_ids_to_remove = []
|
||||
entity_id_queue = [prefab_instance.container_entity for prefab_instance in prefab_instances]
|
||||
while entity_id_queue:
|
||||
entity = entity_id_queue.pop(0)
|
||||
children_entity_ids = entity.get_children_ids()
|
||||
for child_entity_id in children_entity_ids:
|
||||
entity_id_queue.append(EditorEntity(child_entity_id))
|
||||
|
||||
entity_ids_to_remove.append(entity.id)
|
||||
|
||||
container_entity_ids = [prefab_instance.container_entity.id for prefab_instance in prefab_instances]
|
||||
delete_prefab_result = prefab.PrefabPublicRequestBus(bus.Broadcast, 'DeleteEntitiesAndAllDescendantsInInstance', container_entity_ids)
|
||||
assert delete_prefab_result.IsSuccess(), f"Prefab operation 'DeleteEntitiesAndAllDescendantsInInstance' failed. Error: {delete_prefab_result.GetError()}"
|
||||
|
||||
prefab_test_utils.wait_for_propagation()
|
||||
|
||||
entity_ids_after_delete = set(prefab_test_utils.get_all_entities())
|
||||
for entity_id_removed in entity_ids_to_remove:
|
||||
if entity_id_removed in entity_ids_after_delete:
|
||||
assert prefab_entities_deleted, "Not all entities and descendants in target prefabs are deleted."
|
||||
|
||||
for instance in prefab_instances:
|
||||
instance_deleted_prefab = Prefab.get_prefab(instance.prefab_file_name)
|
||||
instance_deleted_prefab.instances.remove(instance)
|
||||
instance = PrefabInstance()
|
||||
|
||||
"""
|
||||
Instantiate an instance of this prefab.
|
||||
:param parent_entity: The entity the prefab should be a child of in the transform hierarchy.
|
||||
:param name: A name for newly instantiated prefab instance. The default instance name is the same as this prefab's file name.
|
||||
:param prefab_position: The position in world space the prefab should be instantiated in.
|
||||
:return: Instantiated PrefabInstance object owned by this prefab.
|
||||
"""
|
||||
def instantiate(self, parent_entity: EditorEntity=None, name: str=None, prefab_position: Vector3=Vector3()) -> PrefabInstance:
|
||||
parent_entity_id = parent_entity.id if parent_entity is not None else EntityId()
|
||||
|
||||
instantiate_prefab_result = prefab.PrefabPublicRequestBus(
|
||||
bus.Broadcast, 'InstantiatePrefab', self.file_path, parent_entity_id, prefab_position)
|
||||
|
||||
assert instantiate_prefab_result.IsSuccess(), f"Prefab operation 'InstantiatePrefab' failed. Error: {instantiate_prefab_result.GetError()}"
|
||||
|
||||
container_entity_id = instantiate_prefab_result.GetValue()
|
||||
container_entity = EditorEntity(container_entity_id)
|
||||
|
||||
if name:
|
||||
container_entity.set_name(name)
|
||||
|
||||
prefab_test_utils.wait_for_propagation()
|
||||
|
||||
new_prefab_instance = PrefabInstance(self.file_name, EditorEntity(container_entity_id))
|
||||
assert not new_prefab_instance in self.instances, "This prefab instance is already existed before this instantiation."
|
||||
self.instances.add(new_prefab_instance)
|
||||
|
||||
prefab_test_utils.check_entity_at_position(container_entity_id, prefab_position)
|
||||
|
||||
return new_prefab_instance
|
||||
@@ -1,82 +0,0 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from azlmbr.entity import EntityId
|
||||
from azlmbr.math import Vector3
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.components as components
|
||||
import azlmbr.entity as entity
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
def get_prefab_file_name(prefab_name):
|
||||
return prefab_name + ".prefab"
|
||||
|
||||
def get_prefab_file_path(prefab_name):
|
||||
return os.path.join(os.path.dirname(os.path.abspath(__file__)), get_prefab_file_name(prefab_name))
|
||||
|
||||
def find_entities_by_name(entity_name):
|
||||
searchFilter = entity.SearchFilter()
|
||||
searchFilter.names = [entity_name]
|
||||
return entity.SearchBus(bus.Broadcast, 'SearchEntities', searchFilter)
|
||||
|
||||
def get_all_entities():
|
||||
return entity.SearchBus(bus.Broadcast, 'SearchEntities', entity.SearchFilter())
|
||||
|
||||
def check_entity_at_position(entity_id, expected_entity_position):
|
||||
entity_at_expected_position_result = (
|
||||
"entity is at expected position",
|
||||
"entity is *not* at expected position")
|
||||
|
||||
actual_entity_position = components.TransformBus(bus.Event, "GetWorldTranslation", entity_id)
|
||||
is_at_position = actual_entity_position.IsClose(expected_entity_position)
|
||||
Report.result(entity_at_expected_position_result, is_at_position)
|
||||
|
||||
if not is_at_position:
|
||||
Report.info(f"Entity '{entity_id.ToString()}'\'s expected position: {expected_entity_position.ToString()}, actual position: {actual_entity_position.ToString()}")
|
||||
|
||||
return is_at_position
|
||||
|
||||
def check_entity_children_count(entity_id, expected_children_count):
|
||||
entity_children_count_matched_result = (
|
||||
"Entity with a unique name found",
|
||||
"Entity with a unique name *not* found")
|
||||
|
||||
entity = EditorEntity(entity_id)
|
||||
children_entity_ids = entity.get_children_ids()
|
||||
entity_children_count_matched = len(children_entity_ids) == expected_children_count
|
||||
Report.result(entity_children_count_matched_result, entity_children_count_matched)
|
||||
|
||||
if not entity_children_count_matched:
|
||||
Report.info(f"Entity '{entity_id.ToString()}' actual children count: {len(children_entity_ids)}. Expected children count: {expected_children_count}")
|
||||
|
||||
return entity_children_count_matched
|
||||
|
||||
def get_children_ids_by_name(entity_id, entity_name):
|
||||
entity = EditorEntity(entity_id)
|
||||
children_entity_ids = entity.get_children_ids()
|
||||
|
||||
result = []
|
||||
for child_entity_id in children_entity_ids:
|
||||
child_entity = EditorEntity(child_entity_id)
|
||||
child_entity_name = child_entity.get_name()
|
||||
if child_entity_name == entity_name:
|
||||
result.append(child_entity_id)
|
||||
|
||||
return result
|
||||
|
||||
def wait_for_propagation():
|
||||
general.idle_wait_frames(1)
|
||||
|
||||
def open_base_tests_level():
|
||||
helper.init_idle()
|
||||
helper.open_level("Prefab", "Base")
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e4937547ca4c486ef59656314401933217e0e0401fec103e1fb91c25ec60a177
|
||||
size 2806
|
||||
oid sha256:a5f9e27e0f22c31ca61d866fb594c6fde5b8ceb891e17dda075fa1e0033ec2b9
|
||||
size 1666
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "AboutDialog.h"
|
||||
|
||||
// Qt
|
||||
@@ -47,14 +44,17 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
|
||||
CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }");
|
||||
|
||||
// Prepare background image
|
||||
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
|
||||
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
|
||||
screen(),
|
||||
QSize(m_enforcedWidth, m_enforcedHeight),
|
||||
QPixmap image = AzQtComponents::ScalePixmapForScreenDpi(
|
||||
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
|
||||
screen(), QSize(m_imageWidth, m_imageHeight),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation
|
||||
);
|
||||
|
||||
// Crop image to cut out transparent border
|
||||
QRect cropRect((m_imageWidth - m_enforcedWidth) / 2, (m_imageHeight - m_enforcedHeight) / 2, m_enforcedWidth, m_enforcedHeight);
|
||||
m_backgroundImage = AzQtComponents::CropPixmapForScreenDpi(image, screen(), cropRect);
|
||||
|
||||
// Draw the Open 3D Engine logo from svg
|
||||
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
|
||||
|
||||
|
||||
@@ -38,7 +38,9 @@ private:
|
||||
QScopedPointer<Ui::CAboutDialog> m_ui;
|
||||
QPixmap m_backgroundImage;
|
||||
|
||||
int m_enforcedWidth = 600;
|
||||
int m_enforcedHeight = 400;
|
||||
const int m_imageWidth = 668;
|
||||
const int m_imageHeight = 368;
|
||||
const int m_enforcedWidth = 600;
|
||||
const int m_enforcedHeight = 300;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>360</height>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -19,13 +19,13 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>360</height>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>360</height>
|
||||
<width>608</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -69,7 +69,7 @@
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>12</number>
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>12</number>
|
||||
@@ -125,7 +125,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Developer Preview</string>
|
||||
<string>General Availability</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
|
||||
@@ -1,923 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ColorGradientCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QToolTip>
|
||||
|
||||
// AzQtComponents
|
||||
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
|
||||
|
||||
|
||||
#define MIN_TIME_EPSILON 0.01f
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CColorGradientCtrl::CColorGradientCtrl(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_nActiveKey = -1;
|
||||
m_nHitKeyIndex = -1;
|
||||
m_nKeyDrawRadius = 3;
|
||||
m_bTracking = false;
|
||||
m_pSpline = nullptr;
|
||||
m_fMinTime = -1;
|
||||
m_fMaxTime = 1;
|
||||
m_fMinValue = -1;
|
||||
m_fMaxValue = 1;
|
||||
m_fTooltipScaleX = 1;
|
||||
m_fTooltipScaleY = 1;
|
||||
m_bNoTimeMarker = true;
|
||||
m_bLockFirstLastKey = false;
|
||||
m_bNoZoom = true;
|
||||
|
||||
ClearSelection();
|
||||
|
||||
m_bSelectedKeys.reserve(0);
|
||||
|
||||
m_fTimeMarker = -10;
|
||||
|
||||
m_grid.zoom.x = 100;
|
||||
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
CColorGradientCtrl::~CColorGradientCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// QColorGradientCtrl message handlers
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
QRect rc(QPoint(0, 0), event->size());
|
||||
m_rcGradient = rc;
|
||||
m_rcGradient.setHeight(m_rcGradient.height() - 11);
|
||||
//m_rcGradient.DeflateRect(4,4);
|
||||
|
||||
m_grid.rect = m_rcGradient;
|
||||
if (m_bNoZoom)
|
||||
{
|
||||
m_grid.zoom.x = static_cast<f32>(m_grid.rect.width());
|
||||
}
|
||||
|
||||
m_rcKeys = rc;
|
||||
m_rcKeys.setTop(m_rcKeys.bottom() - 10);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SetZoom(float fZoom)
|
||||
{
|
||||
m_grid.zoom.x = fZoom;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SetOrigin(float fOffset)
|
||||
{
|
||||
m_grid.origin.x = fOffset;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QPoint CColorGradientCtrl::KeyToPoint(int nKey)
|
||||
{
|
||||
if (nKey >= 0)
|
||||
{
|
||||
return TimeToPoint(m_pSpline->GetKeyTime(nKey));
|
||||
}
|
||||
return QPoint(0, 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QPoint CColorGradientCtrl::TimeToPoint(float time)
|
||||
{
|
||||
return QPoint(m_grid.WorldToClient(Vec2(time, 0)).x(), m_rcGradient.height() / 2);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ::Color CColorGradientCtrl::TimeToColor(float time)
|
||||
{
|
||||
ISplineInterpolator::ValueType val;
|
||||
m_pSpline->Interpolate(time, val);
|
||||
const AZ::Color col = ValueToColor(val);
|
||||
return col;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::PointToTimeValue(QPoint point, float& time, ISplineInterpolator::ValueType& val)
|
||||
{
|
||||
time = XOfsToTime(point.x());
|
||||
ColorToValue(TimeToColor(time), val);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float CColorGradientCtrl::XOfsToTime(int x)
|
||||
{
|
||||
return m_grid.ClientToWorld(QPoint(x, 0)).x;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QPoint CColorGradientCtrl::XOfsToPoint(int x)
|
||||
{
|
||||
return TimeToPoint(XOfsToTime(x));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ::Color CColorGradientCtrl::XOfsToColor(int x)
|
||||
{
|
||||
return TimeToColor(XOfsToTime(x));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::paintEvent(QPaintEvent* e)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
QRect rcClient = rect();
|
||||
|
||||
if (m_pSpline)
|
||||
{
|
||||
m_bSelectedKeys.resize(m_pSpline->GetKeyCount());
|
||||
}
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
painter.setBrush(palette().button());
|
||||
painter.drawRect(rcClient);
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Fill keys backgound.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QRect rcKeys = m_rcKeys.intersected(e->rect());
|
||||
painter.setBrush(palette().button());
|
||||
painter.drawRect(rcKeys);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Draw Keys and Curve
|
||||
if (m_pSpline)
|
||||
{
|
||||
DrawGradient(e, &painter);
|
||||
DrawKeys(e, &painter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::DrawGradient(QPaintEvent* e, QPainter* painter)
|
||||
{
|
||||
//Draw Curve
|
||||
// create and select a thick, white pen
|
||||
painter->setPen(QPen(QColor(128, 255, 128), 1, Qt::SolidLine));
|
||||
|
||||
const QRect rcClip = e->rect().intersected(m_rcGradient);
|
||||
const int right = rcClip.left() + rcClip.width();
|
||||
for (int x = rcClip.left(); x < right; x++)
|
||||
{
|
||||
const AZ::Color col = XOfsToColor(x);
|
||||
QPen pen(QColor(col.GetR8(), col.GetG8(), col.GetR8(), col.GetA8()), 1, Qt::SolidLine);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(x, m_rcGradient.top(), x, m_rcGradient.top() + m_rcGradient.height());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::DrawKeys(QPaintEvent* e, QPainter* painter)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// create and select a white pen
|
||||
painter->setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine));
|
||||
|
||||
QRect rcClip = e->rect();
|
||||
|
||||
m_bSelectedKeys.resize(m_pSpline->GetKeyCount());
|
||||
|
||||
for (int i = 0; i < m_pSpline->GetKeyCount(); i++)
|
||||
{
|
||||
float time = m_pSpline->GetKeyTime(i);
|
||||
QPoint pt = TimeToPoint(time);
|
||||
|
||||
if (pt.x() < rcClip.left() - 8 || pt.x() > rcClip.left() + rcClip.width() + 8)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::Color clr = TimeToColor(time);
|
||||
QBrush brush(QColor(clr.GetR8(), clr.GetG8(), clr.GetB8(), clr.GetA8()));
|
||||
painter->setBrush(brush);
|
||||
|
||||
// Find the midpoints of the top, right, left, and bottom
|
||||
// of the client area. They will be the vertices of our polygon.
|
||||
QPoint pts[3];
|
||||
pts[0].rx() = pt.x();
|
||||
pts[0].ry() = m_rcKeys.top() + 1;
|
||||
pts[1].rx() = pt.x() - 5;
|
||||
pts[1].ry() = m_rcKeys.top() + 8;
|
||||
pts[2].rx() = pt.x() + 5;
|
||||
pts[2].ry() = m_rcKeys.top() + 8;
|
||||
painter->drawPolygon(pts, 3);
|
||||
|
||||
if (m_bSelectedKeys[i])
|
||||
{
|
||||
QPen pen(QColor(200, 0, 0), 1, Qt::SolidLine);
|
||||
QPen oldPen = painter->pen();
|
||||
painter->setPen(pen);
|
||||
painter->drawPolygon(pts, 3);
|
||||
painter->setPen(oldPen);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_bNoTimeMarker)
|
||||
{
|
||||
QPen timePen(QColor(255, 0, 255), 1, Qt::SolidLine);
|
||||
painter->setPen(timePen);
|
||||
QPoint pt = TimeToPoint(m_fTimeMarker);
|
||||
painter->drawLine(pt.x(), m_rcGradient.top() + 1, pt.x(), m_rcGradient.bottom() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CColorGradientCtrl::UpdateTooltip(QPoint pos)
|
||||
{
|
||||
if (m_nHitKeyIndex >= 0)
|
||||
{
|
||||
float time = m_pSpline->GetKeyTime(m_nHitKeyIndex);
|
||||
ISplineInterpolator::ValueType val;
|
||||
m_pSpline->GetKeyValue(m_nHitKeyIndex, val);
|
||||
|
||||
AZ::Color col = TimeToColor(time);
|
||||
int cont_s = (m_pSpline->GetKeyFlags(m_nHitKeyIndex) >> SPLINE_KEY_TANGENT_IN_SHIFT) & SPLINE_KEY_TANGENT_LINEAR ? 1 : 2;
|
||||
int cont_d = (m_pSpline->GetKeyFlags(m_nHitKeyIndex) >> SPLINE_KEY_TANGENT_OUT_SHIFT) & SPLINE_KEY_TANGENT_LINEAR ? 1 : 2;
|
||||
|
||||
QString tipText(tr("%1 : %2,%3,%4 [%5,%6]").arg(time * m_fTooltipScaleX, 0, 'f', 2).arg(col.GetR8()).arg(col.GetG8()).arg(col.GetB8()).arg(cont_s).arg(cont_d));
|
||||
const QPoint globalPos = mapToGlobal(pos);
|
||||
QToolTip::showText(mapToGlobal(pos), tipText, this, QRect(globalPos, QSize(1, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//Mouse Message Handlers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
OnLButtonDown(event);
|
||||
}
|
||||
else if (event->button() == Qt::RightButton)
|
||||
{
|
||||
OnRButtonDown(event);
|
||||
}
|
||||
}
|
||||
|
||||
void CColorGradientCtrl::OnLButtonDown([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
if (m_bTracking)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setFocus();
|
||||
|
||||
switch (m_hitCode)
|
||||
{
|
||||
case HIT_KEY:
|
||||
StartTracking();
|
||||
SetActiveKey(m_nHitKeyIndex);
|
||||
break;
|
||||
|
||||
/*
|
||||
case HIT_SPLINE:
|
||||
{
|
||||
// Cycle the spline slope of the nearest key.
|
||||
int flags = m_pSpline->GetKeyFlags(m_nHitKeyIndex);
|
||||
if (m_nHitKeyDist < 0)
|
||||
// Toggle left side.
|
||||
flags ^= SPLINE_KEY_TANGENT_LINEAR << SPLINE_KEY_TANGENT_IN_SHIFT;
|
||||
if (m_nHitKeyDist > 0)
|
||||
// Toggle right side.
|
||||
flags ^= SPLINE_KEY_TANGENT_LINEAR << SPLINE_KEY_TANGENT_OUT_SHIFT;
|
||||
m_pSpline->SetKeyFlags(m_nHitKeyIndex, flags);
|
||||
m_pSpline->Update();
|
||||
|
||||
SetActiveKey(-1);
|
||||
SendNotifyEvent( CLRGRDN_CHANGE );
|
||||
if (m_updateCallback)
|
||||
m_updateCallback(this);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case HIT_NOTHING:
|
||||
SetActiveKey(-1);
|
||||
break;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::OnRButtonDown([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->button() != Qt::LeftButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_hitCode)
|
||||
{
|
||||
case HIT_SPLINE:
|
||||
{
|
||||
int iIndex = InsertKey(event->pos());
|
||||
SetActiveKey(iIndex);
|
||||
EditKey(iIndex);
|
||||
|
||||
update();
|
||||
}
|
||||
break;
|
||||
case HIT_KEY:
|
||||
{
|
||||
EditKey(m_nHitKeyIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_bTracking)
|
||||
{
|
||||
switch (HitTest(event->pos()))
|
||||
{
|
||||
case HIT_SPLINE:
|
||||
{
|
||||
setCursor(CMFCUtils::LoadCursor(IDC_ARRWHITE));
|
||||
} break;
|
||||
case HIT_KEY:
|
||||
{
|
||||
setCursor(CMFCUtils::LoadCursor(IDC_ARRBLCK));
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bTracking)
|
||||
{
|
||||
TrackKey(event->pos());
|
||||
}
|
||||
|
||||
if (m_bTracking || m_nHitKeyIndex >= 0)
|
||||
{
|
||||
UpdateTooltip(event->pos());
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
}
|
||||
|
||||
void CColorGradientCtrl::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
OnLButtonUp(event);
|
||||
}
|
||||
else if (event->button() == Qt::RightButton)
|
||||
{
|
||||
OnRButtonUp(event);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::OnLButtonUp(QMouseEvent* event)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bTracking)
|
||||
{
|
||||
StopTracking(event->pos());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::OnRButtonUp([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SetActiveKey(int nIndex)
|
||||
{
|
||||
ClearSelection();
|
||||
|
||||
//Activate New Key
|
||||
if (nIndex >= 0)
|
||||
{
|
||||
m_bSelectedKeys[nIndex] = true;
|
||||
}
|
||||
m_nActiveKey = nIndex;
|
||||
update();
|
||||
|
||||
SendNotifyEvent(CLRGRDN_ACTIVE_KEY_CHANGE);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SetSpline(ISplineInterpolator* pSpline, bool bRedraw)
|
||||
{
|
||||
if (pSpline != m_pSpline)
|
||||
{
|
||||
//if (pSpline && pSpline->GetNumDimensions() != 3)
|
||||
//return;
|
||||
m_pSpline = pSpline;
|
||||
m_nActiveKey = -1;
|
||||
}
|
||||
|
||||
ClearSelection();
|
||||
|
||||
if (bRedraw)
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ISplineInterpolator* CColorGradientCtrl::GetSpline()
|
||||
{
|
||||
return m_pSpline;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
bool bProcessed = false;
|
||||
|
||||
if (m_nActiveKey != -1 && m_pSpline)
|
||||
{
|
||||
switch (event->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
{
|
||||
RemoveKey(m_nActiveKey);
|
||||
bProcessed = true;
|
||||
} break;
|
||||
case Qt::Key_Up:
|
||||
{
|
||||
CUndo undo("Move Spline Key");
|
||||
QPoint point = KeyToPoint(m_nActiveKey);
|
||||
point.rx() -= 1;
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
TrackKey(point);
|
||||
bProcessed = true;
|
||||
} break;
|
||||
case Qt::Key_Down:
|
||||
{
|
||||
CUndo undo("Move Spline Key");
|
||||
QPoint point = KeyToPoint(m_nActiveKey);
|
||||
point.rx() += 1;
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
TrackKey(point);
|
||||
bProcessed = true;
|
||||
} break;
|
||||
case Qt::Key_Left:
|
||||
{
|
||||
CUndo undo("Move Spline Key");
|
||||
QPoint point = KeyToPoint(m_nActiveKey);
|
||||
point.rx() -= 1;
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
TrackKey(point);
|
||||
bProcessed = true;
|
||||
} break;
|
||||
case Qt::Key_Right:
|
||||
{
|
||||
CUndo undo("Move Spline Key");
|
||||
QPoint point = KeyToPoint(m_nActiveKey);
|
||||
point.rx() += 1;
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
TrackKey(point);
|
||||
bProcessed = true;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break; //do nothing
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
event->setAccepted(bProcessed);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
CColorGradientCtrl::EHitCode CColorGradientCtrl::HitTest(QPoint point)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return HIT_NOTHING;
|
||||
}
|
||||
|
||||
ISplineInterpolator::ValueType val;
|
||||
float time;
|
||||
PointToTimeValue(point, time, val);
|
||||
|
||||
QRect rc = rect();
|
||||
|
||||
m_nHitKeyIndex = -1;
|
||||
|
||||
if (rc.contains(point))
|
||||
{
|
||||
m_nHitKeyDist = 0xFFFF;
|
||||
m_hitCode = HIT_SPLINE;
|
||||
|
||||
for (int i = 0; i < m_pSpline->GetKeyCount(); i++)
|
||||
{
|
||||
QPoint splinePt = TimeToPoint(m_pSpline->GetKeyTime(i));
|
||||
if (abs(point.x() - splinePt.x()) < abs(m_nHitKeyDist))
|
||||
{
|
||||
m_nHitKeyIndex = i;
|
||||
m_nHitKeyDist = point.x() - splinePt.x();
|
||||
}
|
||||
}
|
||||
if (abs(m_nHitKeyDist) < 4)
|
||||
{
|
||||
m_hitCode = HIT_KEY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hitCode = HIT_NOTHING;
|
||||
}
|
||||
|
||||
return m_hitCode;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::StartTracking()
|
||||
{
|
||||
m_bTracking = true;
|
||||
|
||||
GetIEditor()->BeginUndo();
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
|
||||
setCursor(CMFCUtils::LoadCursor(IDC_ARRBLCKCROSS));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::TrackKey(QPoint point)
|
||||
{
|
||||
if (point.x() < m_rcGradient.left() || point.y() > m_rcGradient.right())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int nKey = m_nHitKeyIndex;
|
||||
|
||||
if (nKey >= 0)
|
||||
{
|
||||
ISplineInterpolator::ValueType val;
|
||||
float time;
|
||||
PointToTimeValue(point, time, val);
|
||||
|
||||
// Clamp to min/max time.
|
||||
if (time < m_fMinTime || time > m_fMaxTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < m_pSpline->GetKeyCount(); i++)
|
||||
{
|
||||
// Switch to next key.
|
||||
if ((m_pSpline->GetKeyTime(i) < time && i > nKey) ||
|
||||
(m_pSpline->GetKeyTime(i) > time && i < nKey))
|
||||
{
|
||||
m_pSpline->SetKeyTime(nKey, time);
|
||||
m_pSpline->Update();
|
||||
SetActiveKey(i);
|
||||
m_nHitKeyIndex = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_bLockFirstLastKey || (nKey != 0 && nKey != m_pSpline->GetKeyCount() - 1))
|
||||
{
|
||||
m_pSpline->SetKeyTime(nKey, time);
|
||||
m_pSpline->Update();
|
||||
}
|
||||
|
||||
SendNotifyEvent(CLRGRDN_CHANGE);
|
||||
if (m_updateCallback)
|
||||
{
|
||||
m_updateCallback(this);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::StopTracking(QPoint point)
|
||||
{
|
||||
if (!m_bTracking)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetIEditor()->AcceptUndo("Spline Move");
|
||||
|
||||
if (m_nHitKeyIndex >= 0)
|
||||
{
|
||||
QRect rc = rect();
|
||||
rc = rc.marginsAdded(QMargins(100, 100, 100, 100));
|
||||
if (!rc.contains(point))
|
||||
{
|
||||
RemoveKey(m_nHitKeyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
m_bTracking = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::EditKey(int nKey)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (nKey < 0 || nKey >= m_pSpline->GetKeyCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetActiveKey(nKey);
|
||||
|
||||
ISplineInterpolator::ValueType val;
|
||||
m_pSpline->GetKeyValue(nKey, val);
|
||||
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
|
||||
AzQtComponents::ColorPicker dlg(AzQtComponents::ColorPicker::Configuration::RGB);
|
||||
dlg.setCurrentColor(ValueToColor(val));
|
||||
dlg.setSelectedColor(ValueToColor(val));
|
||||
connect(&dlg, &AzQtComponents::ColorPicker::currentColorChanged, this, &CColorGradientCtrl::OnKeyColorChanged);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
CUndo undo("Modify Gradient Color");
|
||||
OnKeyColorChanged(dlg.selectedColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
OnKeyColorChanged(ValueToColor(val));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::OnKeyColorChanged(const AZ::Color& color)
|
||||
{
|
||||
int nKey = m_nActiveKey;
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (nKey < 0 || nKey >= m_pSpline->GetKeyCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ISplineInterpolator::ValueType val;
|
||||
ColorToValue(color, val);
|
||||
m_pSpline->SetKeyValue(nKey, val);
|
||||
update();
|
||||
|
||||
if (m_bLockFirstLastKey)
|
||||
{
|
||||
if (nKey == 0)
|
||||
{
|
||||
m_pSpline->SetKeyValue(m_pSpline->GetKeyCount() - 1, val);
|
||||
}
|
||||
else if (nKey == m_pSpline->GetKeyCount() - 1)
|
||||
{
|
||||
m_pSpline->SetKeyValue(0, val);
|
||||
}
|
||||
}
|
||||
m_pSpline->Update();
|
||||
SendNotifyEvent(CLRGRDN_CHANGE);
|
||||
if (m_updateCallback)
|
||||
{
|
||||
m_updateCallback(this);
|
||||
}
|
||||
|
||||
GetIEditor()->UpdateViews(eRedrawViewports);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::RemoveKey(int nKey)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_bLockFirstLastKey)
|
||||
{
|
||||
if (nKey == 0 || nKey == m_pSpline->GetKeyCount() - 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CUndo undo("Remove Spline Key");
|
||||
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
m_nActiveKey = -1;
|
||||
m_nHitKeyIndex = -1;
|
||||
if (m_pSpline)
|
||||
{
|
||||
m_pSpline->RemoveKey(nKey);
|
||||
m_pSpline->Update();
|
||||
}
|
||||
SendNotifyEvent(CLRGRDN_CHANGE);
|
||||
if (m_updateCallback)
|
||||
{
|
||||
m_updateCallback(this);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CColorGradientCtrl::InsertKey(QPoint point)
|
||||
{
|
||||
CUndo undo("Spline Insert Key");
|
||||
|
||||
ISplineInterpolator::ValueType val;
|
||||
|
||||
float time;
|
||||
PointToTimeValue(point, time, val);
|
||||
|
||||
if (time < m_fMinTime || time > m_fMaxTime)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < m_pSpline->GetKeyCount(); i++)
|
||||
{
|
||||
// Skip if any key already have time that is very close.
|
||||
if (fabs(m_pSpline->GetKeyTime(i) - time) < MIN_TIME_EPSILON)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
SendNotifyEvent(CLRGRDN_BEFORE_CHANGE);
|
||||
|
||||
m_pSpline->InsertKey(time, val);
|
||||
m_pSpline->Interpolate(time, val);
|
||||
ClearSelection();
|
||||
update();
|
||||
|
||||
SendNotifyEvent(CLRGRDN_CHANGE);
|
||||
if (m_updateCallback)
|
||||
{
|
||||
m_updateCallback(this);
|
||||
}
|
||||
|
||||
for (i = 0; i < m_pSpline->GetKeyCount(); i++)
|
||||
{
|
||||
// Find key with added time.
|
||||
if (m_pSpline->GetKeyTime(i) == time)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::ClearSelection()
|
||||
{
|
||||
m_nActiveKey = -1;
|
||||
if (m_pSpline)
|
||||
{
|
||||
m_bSelectedKeys.resize(m_pSpline->GetKeyCount());
|
||||
}
|
||||
for (int i = 0; i < (int)m_bSelectedKeys.size(); i++)
|
||||
{
|
||||
m_bSelectedKeys[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SetTimeMarker(float fTime)
|
||||
{
|
||||
if (!m_pSpline)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QPoint pt = TimeToPoint(m_fTimeMarker);
|
||||
QRect rc = QRect(pt.x(), m_rcGradient.top(), 0, m_rcGradient.bottom() - m_rcGradient.top()).normalized();
|
||||
rc += QMargins(1, 0, 1, 0);
|
||||
update(rc);
|
||||
}
|
||||
{
|
||||
QPoint pt = TimeToPoint(fTime);
|
||||
QRect rc = QRect(pt.x(), m_rcGradient.top(), 0, m_rcGradient.bottom() - m_rcGradient.top()).normalized();
|
||||
rc += QMargins(1, 0, 1, 0);
|
||||
update(rc);
|
||||
}
|
||||
m_fTimeMarker = fTime;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::SendNotifyEvent(int nEvent)
|
||||
{
|
||||
switch (nEvent)
|
||||
{
|
||||
case CLRGRDN_BEFORE_CHANGE:
|
||||
emit beforeChange();
|
||||
break;
|
||||
case CLRGRDN_CHANGE:
|
||||
emit change();
|
||||
break;
|
||||
case CLRGRDN_ACTIVE_KEY_CHANGE:
|
||||
emit activeKeyChange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ::Color CColorGradientCtrl::ValueToColor(ISplineInterpolator::ValueType val)
|
||||
{
|
||||
const AZ::Color color(val[0], val[1], val[2], 1.0);
|
||||
return color.LinearToGamma();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CColorGradientCtrl::ColorToValue(const AZ::Color& col, ISplineInterpolator::ValueType& val)
|
||||
{
|
||||
const AZ::Color colLin = col.GammaToLinear();
|
||||
val[0] = colLin.GetR();
|
||||
val[1] = colLin.GetG();
|
||||
val[2] = colLin.GetB();
|
||||
val[3] = 0;
|
||||
}
|
||||
|
||||
void CColorGradientCtrl::SetNoTimeMarker(bool noTimeMarker)
|
||||
{
|
||||
m_bNoTimeMarker = noTimeMarker;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
#include <Controls/moc_ColorGradientCtrl.cpp>
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_CONTROLS_COLORGRADIENTCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_CONTROLS_COLORGRADIENTCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#include <ISplines.h>
|
||||
#include "Controls/WndGridHelper.h"
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Color;
|
||||
}
|
||||
|
||||
// Notify event sent when spline is being modified.
|
||||
#define CLRGRDN_CHANGE (0x0001)
|
||||
// Notify event sent just before when spline is modified.
|
||||
#define CLRGRDN_BEFORE_CHANGE (0x0002)
|
||||
// Notify event sent when the active key changes
|
||||
#define CLRGRDN_ACTIVE_KEY_CHANGE (0x0003)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Spline control.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CColorGradientCtrl
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CColorGradientCtrl(QWidget* parent = nullptr);
|
||||
virtual ~CColorGradientCtrl();
|
||||
|
||||
//Key functions
|
||||
int GetActiveKey() { return m_nActiveKey; };
|
||||
void SetActiveKey(int nIndex);
|
||||
int InsertKey(QPoint point);
|
||||
|
||||
// Turns on/off zooming and scroll support.
|
||||
void SetNoZoom([[maybe_unused]] bool bNoZoom) { m_bNoZoom = false; };
|
||||
|
||||
void SetTimeRange(float tmin, float tmax) { m_fMinTime = tmin; m_fMaxTime = tmax; }
|
||||
void SetValueRange(float tmin, float tmax) { m_fMinValue = tmin; m_fMaxValue = tmax; }
|
||||
void SetTooltipValueScale(float x, float y) { m_fTooltipScaleX = x; m_fTooltipScaleY = y; };
|
||||
// Lock value of first and last key to be the same.
|
||||
void LockFirstAndLastKeys(bool bLock) { m_bLockFirstLastKey = bLock; }
|
||||
|
||||
void SetSpline(ISplineInterpolator* pSpline, bool bRedraw = false);
|
||||
ISplineInterpolator* GetSpline();
|
||||
|
||||
void SetTimeMarker(float fTime);
|
||||
|
||||
// Zoom in pixels per time unit.
|
||||
void SetZoom(float fZoom);
|
||||
void SetOrigin(float fOffset);
|
||||
|
||||
typedef AZStd::function<void(CColorGradientCtrl*)> UpdateCallback;
|
||||
void SetUpdateCallback(const UpdateCallback& cb) { m_updateCallback = cb; };
|
||||
|
||||
void SetNoTimeMarker(bool noTimeMarker);
|
||||
|
||||
signals:
|
||||
void change();
|
||||
void beforeChange();
|
||||
void activeKeyChange();
|
||||
|
||||
protected:
|
||||
enum EHitCode
|
||||
{
|
||||
HIT_NOTHING,
|
||||
HIT_KEY,
|
||||
HIT_SPLINE,
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent* e) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
void OnLButtonDown(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void OnLButtonUp(QMouseEvent* event);
|
||||
void OnRButtonUp(QMouseEvent* event);
|
||||
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
void OnRButtonDown(QMouseEvent* event);
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
// Drawing functions
|
||||
void DrawGradient(QPaintEvent* e, QPainter* painter);
|
||||
void DrawKeys(QPaintEvent* e, QPainter* painter);
|
||||
void UpdateTooltip(QPoint pos);
|
||||
|
||||
EHitCode HitTest(QPoint point);
|
||||
|
||||
//Tracking support helper functions
|
||||
void StartTracking();
|
||||
void TrackKey(QPoint point);
|
||||
void StopTracking(QPoint point);
|
||||
void RemoveKey(int nKey);
|
||||
void EditKey(int nKey);
|
||||
|
||||
QPoint KeyToPoint(int nKey);
|
||||
QPoint TimeToPoint(float time);
|
||||
void PointToTimeValue(QPoint point, float& time, ISplineInterpolator::ValueType& val);
|
||||
float XOfsToTime(int x);
|
||||
QPoint XOfsToPoint(int x);
|
||||
|
||||
AZ::Color XOfsToColor(int x);
|
||||
AZ::Color TimeToColor(float time);
|
||||
|
||||
void ClearSelection();
|
||||
|
||||
void SendNotifyEvent(int nEvent);
|
||||
|
||||
AZ::Color ValueToColor(ISplineInterpolator::ValueType val);
|
||||
void ColorToValue(const AZ::Color& col, ISplineInterpolator::ValueType& val);
|
||||
|
||||
|
||||
private:
|
||||
void OnKeyColorChanged(const AZ::Color& color);
|
||||
|
||||
private:
|
||||
ISplineInterpolator* m_pSpline;
|
||||
|
||||
bool m_bNoZoom;
|
||||
|
||||
QRect m_rcClipRect;
|
||||
QRect m_rcGradient;
|
||||
QRect m_rcKeys;
|
||||
|
||||
QPoint m_hitPoint;
|
||||
EHitCode m_hitCode;
|
||||
int m_nHitKeyIndex;
|
||||
int m_nHitKeyDist;
|
||||
QPoint m_curvePoint;
|
||||
|
||||
float m_fTimeMarker;
|
||||
|
||||
int m_nActiveKey;
|
||||
int m_nKeyDrawRadius;
|
||||
|
||||
bool m_bTracking;
|
||||
|
||||
float m_fMinTime, m_fMaxTime;
|
||||
float m_fMinValue, m_fMaxValue;
|
||||
float m_fTooltipScaleX, m_fTooltipScaleY;
|
||||
|
||||
bool m_bLockFirstLastKey;
|
||||
|
||||
bool m_bNoTimeMarker;
|
||||
|
||||
std::vector<int> m_bSelectedKeys;
|
||||
|
||||
UpdateCallback m_updateCallback;
|
||||
|
||||
CWndGridHelper m_grid;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_CONTROLS_COLORGRADIENTCTRL_H
|
||||
@@ -27,7 +27,6 @@ void RegisterReflectedVarHandlers()
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LightAnimationPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew UserPopupWidgetHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ColorCurveHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FloatCurveHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew MotionPropertyWidgetHandler());
|
||||
}
|
||||
|
||||
@@ -170,30 +170,3 @@ bool FloatCurveHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, CSpline
|
||||
GUI->SetSpline(reinterpret_cast<ISplineInterpolator*>(instance.m_spline));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QWidget* ColorCurveHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
CColorGradientCtrl* gradientCtrl = new CColorGradientCtrl(pParent);
|
||||
//connect(gradientCtrl, &CColorGradientCtrl::change, [gradientCtrl]()
|
||||
//{
|
||||
// EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, gradientCtrl);
|
||||
//});
|
||||
gradientCtrl->SetTimeRange(0, 1);
|
||||
gradientCtrl->setFixedHeight(36);
|
||||
return gradientCtrl;
|
||||
|
||||
}
|
||||
|
||||
void ColorCurveHandler::ConsumeAttribute(CColorGradientCtrl*, AZ::u32, AzToolsFramework::PropertyAttributeReader*, const char*)
|
||||
{}
|
||||
|
||||
void ColorCurveHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, [[maybe_unused]] CColorGradientCtrl* GUI, [[maybe_unused]] property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{}
|
||||
|
||||
bool ColorCurveHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, CColorGradientCtrl* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
GUI->SetSpline(reinterpret_cast<ISplineInterpolator*>(instance.m_spline));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include "Util/VariablePropertyType.h"
|
||||
#include "Controls/ColorGradientCtrl.h"
|
||||
#include "Controls/SplineCtrl.h"
|
||||
#include <QWidget>
|
||||
#endif
|
||||
@@ -82,17 +81,4 @@ public:
|
||||
void OnSplineChange(CSplineCtrl*);
|
||||
};
|
||||
|
||||
class ColorCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CColorGradientCtrl>
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ColorCurveHandler, AZ::SystemAllocator, 0);
|
||||
bool IsDefaultHandler() const override { return false; }
|
||||
QWidget* CreateGUI(QWidget *pParent) override;
|
||||
|
||||
AZ::u32 GetHandlerName(void) const override { return AZ_CRC("ePropertyColorCurve", 0xa30da4ec); }
|
||||
|
||||
void ConsumeAttribute(CColorGradientCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
void WriteGUIValuesIntoProperty(size_t index, CColorGradientCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
bool ReadValuesIntoGUI(size_t index, CColorGradientCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
|
||||
|
||||
@@ -16,18 +16,11 @@
|
||||
#include <QScopedValueRollback>
|
||||
#include <QToolBar>
|
||||
#include <QLoggingCategory>
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
// AzFramework
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
# include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
|
||||
#endif // defined(AZ_PLATFORM_WINDOWS)
|
||||
|
||||
// AzQtComponents
|
||||
#include <AzQtComponents/Components/GlobalEventFilter.h>
|
||||
@@ -39,7 +32,6 @@
|
||||
#include "Settings.h"
|
||||
#include "CryEdit.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
// in milliseconds
|
||||
@@ -241,7 +233,6 @@ namespace Editor
|
||||
|
||||
EditorQtApplication::EditorQtApplication(int& argc, char** argv)
|
||||
: AzQtApplication(argc, argv)
|
||||
, m_inWinEventFilter(false)
|
||||
, m_stylesheet(new AzQtComponents::O3DEStylesheet(this))
|
||||
, m_idleTimer(new QTimer(this))
|
||||
{
|
||||
@@ -368,86 +359,10 @@ namespace Editor
|
||||
UninstallEditorTranslators();
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
bool EditorQtApplication::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long* result)
|
||||
EditorQtApplication* EditorQtApplication::instance()
|
||||
{
|
||||
MSG* msg = (MSG*)message;
|
||||
|
||||
if (msg->message == WM_MOVING || msg->message == WM_SIZING)
|
||||
{
|
||||
m_isMovingOrResizing = true;
|
||||
}
|
||||
else if (msg->message == WM_EXITSIZEMOVE)
|
||||
{
|
||||
m_isMovingOrResizing = false;
|
||||
}
|
||||
|
||||
// Prevent the user from being able to move the window in game mode.
|
||||
// This is done during the hit test phase to bypass the native window move messages. If the window
|
||||
// decoration wrapper title bar contains the cursor, set the result to HTCLIENT instead of
|
||||
// HTCAPTION.
|
||||
if (msg->message == WM_NCHITTEST && GetIEditor()->IsInGameMode())
|
||||
{
|
||||
const LRESULT defWinProcResult = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
||||
if (defWinProcResult == 1)
|
||||
{
|
||||
if (QWidget* widget = QWidget::find((WId)msg->hwnd))
|
||||
{
|
||||
if (auto wrapper = qobject_cast<const AzQtComponents::WindowDecorationWrapper *>(widget))
|
||||
{
|
||||
AzQtComponents::TitleBar* titleBar = wrapper->titleBar();
|
||||
const short global_x = static_cast<short>(LOWORD(msg->lParam));
|
||||
const short global_y = static_cast<short>(HIWORD(msg->lParam));
|
||||
|
||||
const QPoint globalPos = QHighDpi::fromNativePixels(QPoint(global_x, global_y), widget->window()->windowHandle());
|
||||
const QPoint local = titleBar->mapFromGlobal(globalPos);
|
||||
if (titleBar->draggableRect().contains(local) && !titleBar->isTopResizeArea(globalPos))
|
||||
{
|
||||
*result = HTCLIENT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system.
|
||||
// These events are only broadcast in game mode. In Editor mode, RenderViewportWidget creates synthetic
|
||||
// keyboard and mouse events via Qt.
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
if (msg->message == WM_INPUT)
|
||||
{
|
||||
UINT rawInputSize;
|
||||
const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
|
||||
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &rawInputSize, rawInputHeaderSize);
|
||||
|
||||
AZStd::array<BYTE, sizeof(RAWINPUT)> rawInputBytesArray;
|
||||
LPBYTE rawInputBytes = rawInputBytesArray.data();
|
||||
|
||||
[[maybe_unused]] const UINT bytesCopied = GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize);
|
||||
CRY_ASSERT(bytesCopied == rawInputSize);
|
||||
|
||||
RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes;
|
||||
CRY_ASSERT(rawInput);
|
||||
|
||||
AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (msg->message == WM_DEVICECHANGE)
|
||||
{
|
||||
if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED
|
||||
{
|
||||
AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return static_cast<EditorQtApplication*>(QApplication::instance());
|
||||
}
|
||||
#endif
|
||||
|
||||
void EditorQtApplication::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
{
|
||||
@@ -505,11 +420,6 @@ namespace Editor
|
||||
return m_stylesheet->GetColorByName(name);
|
||||
}
|
||||
|
||||
EditorQtApplication* EditorQtApplication::instance()
|
||||
{
|
||||
return static_cast<EditorQtApplication*>(QApplication::instance());
|
||||
}
|
||||
|
||||
bool EditorQtApplication::IsActive()
|
||||
{
|
||||
return applicationState() == Qt::ApplicationActive;
|
||||
@@ -613,42 +523,6 @@ namespace Editor
|
||||
case QEvent::KeyRelease:
|
||||
m_pressedKeys.remove(reinterpret_cast<QKeyEvent*>(event)->key());
|
||||
break;
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
case QEvent::Leave:
|
||||
{
|
||||
// if we receive a leave event for a toolbar on Windows
|
||||
// check first whether we really left it. If we didn't: start checking
|
||||
// for the tool bar under the mouse by timer to check when we really left.
|
||||
// Synthesize a new leave event then. Workaround for LY-69788
|
||||
auto toolBarAt = [](const QPoint& pos) -> QToolBar* {
|
||||
QWidget* widget = qApp->widgetAt(pos);
|
||||
while (widget != nullptr)
|
||||
{
|
||||
if (QToolBar* tb = qobject_cast<QToolBar*>(widget))
|
||||
{
|
||||
return tb;
|
||||
}
|
||||
widget = widget->parentWidget();
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
if (object == toolBarAt(QCursor::pos()))
|
||||
{
|
||||
QTimer* t = new QTimer(object);
|
||||
t->start(100);
|
||||
connect(t, &QTimer::timeout, object, [t, object, toolBarAt]() {
|
||||
if (object != toolBarAt(QCursor::pos()))
|
||||
{
|
||||
QEvent event(QEvent::Leave);
|
||||
qApp->sendEvent(object, &event);
|
||||
t->deleteLater();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -72,14 +72,12 @@ namespace Editor
|
||||
////
|
||||
|
||||
static EditorQtApplication* instance();
|
||||
static EditorQtApplication* newInstance(int& argc, char** argv);
|
||||
|
||||
static bool IsActive();
|
||||
|
||||
bool isMovingOrResizing() const;
|
||||
|
||||
// QAbstractNativeEventFilter:
|
||||
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
|
||||
// IEditorNotifyListener:
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
|
||||
@@ -100,6 +98,10 @@ namespace Editor
|
||||
signals:
|
||||
void skinChanged();
|
||||
|
||||
protected:
|
||||
|
||||
bool m_isMovingOrResizing = false;
|
||||
|
||||
private:
|
||||
enum TimerResetFlag
|
||||
{
|
||||
@@ -116,8 +118,6 @@ namespace Editor
|
||||
|
||||
AzQtComponents::O3DEStylesheet* m_stylesheet;
|
||||
|
||||
bool m_inWinEventFilter = false;
|
||||
|
||||
// Translators
|
||||
void InstallEditorTranslators();
|
||||
void UninstallEditorTranslators();
|
||||
@@ -127,7 +127,6 @@ namespace Editor
|
||||
QTranslator* m_editorTranslator = nullptr;
|
||||
QTranslator* m_assetBrowserTranslator = nullptr;
|
||||
QTimer* const m_idleTimer = nullptr;
|
||||
bool m_isMovingOrResizing = false;
|
||||
|
||||
AZ::UserSettingsProvider m_localUserSettings;
|
||||
|
||||
|
||||
+21
-23
@@ -287,21 +287,22 @@ bool CCryDocManager::DoPromptFileName(QString& fileName, [[maybe_unused]] UINT n
|
||||
|
||||
return false;
|
||||
}
|
||||
CCryEditDoc* CCryDocManager::OpenDocumentFile(const char* lpszFileName, bool bAddToMRU)
|
||||
CCryEditDoc* CCryDocManager::OpenDocumentFile(const char* filename, bool addToMostRecentFileList, COpenSameLevelOptions openSameLevelOptions)
|
||||
{
|
||||
assert(lpszFileName != nullptr);
|
||||
assert(filename != nullptr);
|
||||
|
||||
const bool reopenIfSame = openSameLevelOptions == COpenSameLevelOptions::ReopenLevelIfSame;
|
||||
// find the highest confidence
|
||||
auto pos = m_templateList.begin();
|
||||
CCrySingleDocTemplate::Confidence bestMatch = CCrySingleDocTemplate::noAttempt;
|
||||
CCrySingleDocTemplate* pBestTemplate = nullptr;
|
||||
CCryEditDoc* pOpenDocument = nullptr;
|
||||
|
||||
if (lpszFileName[0] == '\"')
|
||||
if (filename[0] == '\"')
|
||||
{
|
||||
++lpszFileName;
|
||||
++filename;
|
||||
}
|
||||
QString szPath = QString::fromUtf8(lpszFileName);
|
||||
QString szPath = QString::fromUtf8(filename);
|
||||
if (szPath.endsWith('"'))
|
||||
{
|
||||
szPath.remove(szPath.length() - 1, 1);
|
||||
@@ -325,7 +326,7 @@ CCryEditDoc* CCryDocManager::OpenDocumentFile(const char* lpszFileName, bool bAd
|
||||
}
|
||||
}
|
||||
|
||||
if (pOpenDocument != nullptr)
|
||||
if (!reopenIfSame && pOpenDocument != nullptr)
|
||||
{
|
||||
return pOpenDocument;
|
||||
}
|
||||
@@ -336,7 +337,7 @@ CCryEditDoc* CCryDocManager::OpenDocumentFile(const char* lpszFileName, bool bAd
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pBestTemplate->OpenDocumentFile(szPath.toUtf8().data(), bAddToMRU, false);
|
||||
return pBestTemplate->OpenDocumentFile(szPath.toUtf8().data(), addToMostRecentFileList, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -818,7 +819,7 @@ CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, b
|
||||
return OpenDocumentFile(lpszPathName, true, bMakeVisible);
|
||||
}
|
||||
|
||||
CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, bool bAddToMRU, [[maybe_unused]] bool bMakeVisible)
|
||||
CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, bool addToMostRecentFileList, [[maybe_unused]] bool bMakeVisible)
|
||||
{
|
||||
CCryEditDoc* pCurDoc = GetIEditor()->GetDocument();
|
||||
|
||||
@@ -848,7 +849,7 @@ CCryEditDoc* CCrySingleDocTemplate::OpenDocumentFile(const char* lpszPathName, b
|
||||
{
|
||||
pCurDoc->OnOpenDocument(lpszPathName);
|
||||
pCurDoc->SetPathName(lpszPathName);
|
||||
if (bAddToMRU)
|
||||
if (addToMostRecentFileList)
|
||||
{
|
||||
CCryEditApp::instance()->AddToRecentFileList(lpszPathName);
|
||||
}
|
||||
@@ -2631,7 +2632,7 @@ void CCryEditApp::OnShowHelpers()
|
||||
void CCryEditApp::OnEditLevelData()
|
||||
{
|
||||
auto dir = QFileInfo(GetIEditor()->GetDocument()->GetLevelPathName()).dir();
|
||||
CFileUtil::EditTextFile(dir.absoluteFilePath("LevelData.xml").toUtf8().data());
|
||||
CFileUtil::EditTextFile(dir.absoluteFilePath("leveldata.xml").toUtf8().data());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -3365,7 +3366,7 @@ void CCryEditApp::OnOpenSlice()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* lpszFileName)
|
||||
CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* filename, bool addToMostRecentFileList, COpenSameLevelOptions openSameLevelOptions)
|
||||
{
|
||||
if (m_openingLevel)
|
||||
{
|
||||
@@ -3405,9 +3406,9 @@ CCryEditDoc* CCryEditApp::OpenDocumentFile(const char* lpszFileName)
|
||||
openDocTraceHandler.SetShowWindow(false);
|
||||
}
|
||||
|
||||
// in this case, we set bAddToMRU to always be true because adding files to the MRU list
|
||||
// in this case, we set addToMostRecentFileList to always be true because adding files to the MRU list
|
||||
// automatically culls duplicate and normalizes paths anyway
|
||||
m_pDocManager->OpenDocumentFile(lpszFileName, true);
|
||||
m_pDocManager->OpenDocumentFile(filename, addToMostRecentFileList, openSameLevelOptions);
|
||||
|
||||
if (openDocTraceHandler.HasAnyErrors())
|
||||
{
|
||||
@@ -4134,9 +4135,9 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
Editor::EditorQtApplication::InstallQtLogHandler();
|
||||
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
Editor::EditorQtApplication app(argc, argv);
|
||||
Editor::EditorQtApplication* app = Editor::EditorQtApplication::newInstance(argc, argv);
|
||||
|
||||
if (app.arguments().contains("-autotest_mode"))
|
||||
if (app->arguments().contains("-autotest_mode"))
|
||||
{
|
||||
// Nullroute all stdout to null for automated tests, this way we make sure
|
||||
// that the test result output is not polluted with unrelated output data.
|
||||
@@ -4172,12 +4173,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyQtApplicationAvailable, &app);
|
||||
|
||||
#if defined(AZ_PLATFORM_MAC)
|
||||
// Native menu bars do not work on macOS due to all the tool dialogs
|
||||
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
|
||||
#endif
|
||||
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyQtApplicationAvailable, app);
|
||||
|
||||
int exitCode = 0;
|
||||
|
||||
@@ -4188,9 +4184,9 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
|
||||
if (didCryEditStart)
|
||||
{
|
||||
app.EnableOnIdle();
|
||||
app->EnableOnIdle();
|
||||
|
||||
ret = app.exec();
|
||||
ret = app->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4201,6 +4197,8 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
|
||||
|
||||
}
|
||||
|
||||
delete app;
|
||||
|
||||
gSettings.Disconnect();
|
||||
|
||||
return ret;
|
||||
|
||||
+11
-3
@@ -85,6 +85,12 @@ public:
|
||||
|
||||
using EditorIdleProcessingBus = AZ::EBus<EditorIdleProcessing>;
|
||||
|
||||
enum class COpenSameLevelOptions
|
||||
{
|
||||
ReopenLevelIfSame,
|
||||
NotReopenIfSame
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
class SANDBOX_API CCryEditApp
|
||||
@@ -174,7 +180,9 @@ public:
|
||||
virtual bool InitInstance();
|
||||
virtual int ExitInstance(int exitCode = 0);
|
||||
virtual bool OnIdle(LONG lCount);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* lpszFileName);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* filename,
|
||||
bool addToMostRecentFileList=true,
|
||||
COpenSameLevelOptions openSameLevelOptions = COpenSameLevelOptions::NotReopenIfSame);
|
||||
|
||||
CCryDocManager* GetDocManager() { return m_pDocManager; }
|
||||
|
||||
@@ -448,7 +456,7 @@ public:
|
||||
~CCrySingleDocTemplate() {};
|
||||
// avoid creating another CMainFrame
|
||||
// close other type docs before opening any things
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool bAddToMRU, bool bMakeVisible);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool addToMostRecentFileList, bool bMakeVisible);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool bMakeVisible = TRUE);
|
||||
virtual Confidence MatchDocType(const char* lpszPathName, CCryEditDoc*& rpDocMatch);
|
||||
|
||||
@@ -468,7 +476,7 @@ public:
|
||||
virtual void OnFileNew();
|
||||
virtual bool DoPromptFileName(QString& fileName, UINT nIDSTitle,
|
||||
DWORD lFlags, bool bOpenFileDialog, CDocTemplate* pTemplate);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* lpszFileName, bool bAddToMRU);
|
||||
virtual CCryEditDoc* OpenDocumentFile(const char* filename, bool addToMostRecentFileList, COpenSameLevelOptions openSameLevelOptions = COpenSameLevelOptions::NotReopenIfSame);
|
||||
|
||||
QVector<CCrySingleDocTemplate*> m_templateList;
|
||||
};
|
||||
|
||||
+11
-13
@@ -143,20 +143,11 @@ namespace
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const bool addToMostRecentFileList = false;
|
||||
auto newDocument = CCryEditApp::instance()->OpenDocumentFile(levelPath.toUtf8().data(),
|
||||
addToMostRecentFileList, COpenSameLevelOptions::ReopenLevelIfSame);
|
||||
|
||||
auto previousDocument = GetIEditor()->GetDocument();
|
||||
QString previousPathName = (previousDocument != nullptr) ? previousDocument->GetLevelPathName() : "";
|
||||
auto newDocument = CCryEditApp::instance()->OpenDocumentFile(levelPath.toUtf8().data());
|
||||
|
||||
// the underlying document pointer doesn't change, so we can't check that; use the path name's instead
|
||||
|
||||
bool result = true;
|
||||
if (newDocument == nullptr || newDocument->IsLevelLoadFailed() || (newDocument->GetLevelPathName() == previousPathName))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
return newDocument != nullptr && !newDocument->IsLevelLoadFailed();
|
||||
}
|
||||
|
||||
bool PyOpenLevelNoPrompt(const char* pLevelName)
|
||||
@@ -407,6 +398,11 @@ inline namespace Commands
|
||||
{
|
||||
return AZ::Debug::Trace::WaitForDebugger(timeoutSeconds);
|
||||
}
|
||||
|
||||
AZStd::string PyGetFileAlias(AZStd::string alias)
|
||||
{
|
||||
return AZ::IO::FileIOBase::GetInstance()->GetAlias(alias.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
namespace AzToolsFramework
|
||||
@@ -457,6 +453,8 @@ namespace AzToolsFramework
|
||||
addLegacyGeneral(behaviorContext->Method("attach_debugger", PyAttachDebugger, nullptr, "Prompts for attaching the debugger"));
|
||||
addLegacyGeneral(behaviorContext->Method("wait_for_debugger", PyWaitForDebugger, behaviorContext->MakeDefaultValues(-1.f), "Pauses this thread execution until the debugger has been attached"));
|
||||
|
||||
addLegacyGeneral(behaviorContext->Method("get_file_alias", PyGetFileAlias, nullptr, "Retrieves path for IO alias"));
|
||||
|
||||
// this will put these methods into the 'azlmbr.legacy.checkout_dialog' module
|
||||
auto addCheckoutDialog = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
|
||||
{
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define MUSIC_LEVEL_LIBRARY_FILE "Music.xml"
|
||||
#define MATERIAL_LEVEL_LIBRARY_FILE "Materials.xml"
|
||||
#define RESOURCE_LIST_FILE "ResourceList.txt"
|
||||
#define USED_RESOURCE_LIST_FILE "UsedResourceList.txt"
|
||||
#define SHADER_LIST_FILE "ShadersList.txt"
|
||||
#define MUSIC_LEVEL_LIBRARY_FILE "music.xml"
|
||||
#define MATERIAL_LEVEL_LIBRARY_FILE "materials.xml"
|
||||
#define RESOURCE_LIST_FILE "resourcelist.txt"
|
||||
#define USED_RESOURCE_LIST_FILE "usedresourcelist.txt"
|
||||
#define SHADER_LIST_FILE "shaderslist.txt"
|
||||
|
||||
#define GetAValue(rgb) ((BYTE)((rgb) >> 24))
|
||||
|
||||
@@ -185,9 +185,9 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE
|
||||
ExportOcclusionMesh(sLevelPath.toUtf8().data());
|
||||
|
||||
//! Export Level data.
|
||||
CLogFile::WriteLine("Exporting LevelData.xml");
|
||||
CLogFile::WriteLine("Exporting leveldata.xml");
|
||||
ExportLevelData(sLevelPath);
|
||||
CLogFile::WriteLine("Exporting LevelData.xml done.");
|
||||
CLogFile::WriteLine("Exporting leveldata.xml done.");
|
||||
|
||||
ExportLevelInfo(sLevelPath);
|
||||
|
||||
@@ -266,26 +266,26 @@ void CGameExporter::ExportOcclusionMesh(const char* pszGamePath)
|
||||
void CGameExporter::ExportLevelData(const QString& path, bool /*bExportMission*/)
|
||||
{
|
||||
IEditor* pEditor = GetIEditor();
|
||||
pEditor->SetStatusText(QObject::tr("Exporting LevelData.xml..."));
|
||||
pEditor->SetStatusText(QObject::tr("Exporting leveldata.xml..."));
|
||||
|
||||
char versionString[256];
|
||||
pEditor->GetFileVersion().ToString(versionString);
|
||||
|
||||
XmlNodeRef root = XmlHelpers::CreateXmlNode("LevelData");
|
||||
XmlNodeRef root = XmlHelpers::CreateXmlNode("leveldata");
|
||||
root->setAttr("SandboxVersion", versionString);
|
||||
XmlNodeRef rootAction = XmlHelpers::CreateXmlNode("LevelDataAction");
|
||||
XmlNodeRef rootAction = XmlHelpers::CreateXmlNode("leveldataaction");
|
||||
rootAction->setAttr("SandboxVersion", versionString);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Save Level Data XML
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString levelDataFile = path + "LevelData.xml";
|
||||
QString levelDataFile = path + "leveldata.xml";
|
||||
XmlString xmlData = root->getXML();
|
||||
CCryMemFile file;
|
||||
file.Write(xmlData.c_str(), static_cast<unsigned int>(xmlData.length()));
|
||||
m_levelPak.m_pakFile.UpdateFile(levelDataFile.toUtf8().data(), file);
|
||||
|
||||
QString levelDataActionFile = path + "LevelDataAction.xml";
|
||||
QString levelDataActionFile = path + "leveldataaction.xml";
|
||||
XmlString xmlDataAction = rootAction->getXML();
|
||||
CCryMemFile fileAction;
|
||||
fileAction.Write(xmlDataAction.c_str(), static_cast<unsigned int>(xmlDataAction.length()));
|
||||
@@ -298,7 +298,7 @@ void CGameExporter::ExportLevelData(const QString& path, bool /*bExportMission*/
|
||||
if (savedEntities)
|
||||
{
|
||||
QString entitiesFile;
|
||||
entitiesFile = QStringLiteral("%1%2.entities_xml").arg(path, "Mission0");
|
||||
entitiesFile = QStringLiteral("%1%2.entities_xml").arg(path, "mission0");
|
||||
m_levelPak.m_pakFile.UpdateFile(entitiesFile.toUtf8().data(), entitySaveBuffer.begin(), static_cast<int>(entitySaveBuffer.size()));
|
||||
}
|
||||
}
|
||||
@@ -326,7 +326,7 @@ void CGameExporter::ExportLevelInfo(const QString& path)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Save LevelInfo file.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString filename = path + "LevelInfo.xml";
|
||||
QString filename = path + "levelinfo.xml";
|
||||
XmlString xmlData = root->getXML();
|
||||
|
||||
CCryMemFile file;
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace UnitTest
|
||||
void BeginCursorCapture() override;
|
||||
void EndCursorCapture() override;
|
||||
bool IsMouseOver() const override;
|
||||
void SetOverrideCursor(AzToolsFramework::ViewportInteraction::CursorStyleOverride cursorStyleOverride) override;
|
||||
void ClearOverrideCursor() override;
|
||||
|
||||
private:
|
||||
AzToolsFramework::QtEventToAzInputMapper* m_inputChannelMapper = nullptr;
|
||||
@@ -58,6 +60,17 @@ namespace UnitTest
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewportMouseCursorRequestImpl::SetOverrideCursor(
|
||||
[[maybe_unused]] AzToolsFramework::ViewportInteraction::CursorStyleOverride cursorStyleOverride)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void ViewportMouseCursorRequestImpl::ClearOverrideCursor()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
class ModularViewportCameraControllerFixture : public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
|
||||
+11
-2
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "QtEditorApplication.h"
|
||||
#include "QtEditorApplication_linux.h"
|
||||
|
||||
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
#include <AzFramework/XcbEventHandler.h>
|
||||
@@ -14,7 +14,16 @@
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
bool EditorQtApplication::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long*)
|
||||
EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
|
||||
{
|
||||
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return new EditorQtApplicationXcb(argc, argv);
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EditorQtApplicationXcb::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long*)
|
||||
{
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Editor/Core/QtEditorApplication.h>
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
class EditorQtApplicationXcb : public EditorQtApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EditorQtApplicationXcb(int& argc, char** argv)
|
||||
: EditorQtApplication(argc, argv)
|
||||
{
|
||||
}
|
||||
|
||||
// QAbstractNativeEventFilter:
|
||||
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
};
|
||||
} // namespace Editor
|
||||
@@ -7,6 +7,6 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../Core/QtEditorApplication_linux.cpp
|
||||
Editor/Core/QtEditorApplication_linux.cpp
|
||||
../Common/Unimplemented/Util/Mailer_Unimplemented.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Editor/Core/QtEditorApplication.h>
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
class EditorQtApplicationMac : public EditorQtApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EditorQtApplicationMac(int& argc, char** argv)
|
||||
: EditorQtApplication(argc, argv)
|
||||
{
|
||||
}
|
||||
|
||||
// QAbstractNativeEventFilter:
|
||||
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
};
|
||||
} // namespace Editor
|
||||
+8
-1
@@ -19,7 +19,14 @@
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
bool EditorQtApplication::nativeEventFilter(const QByteArray& eventType, void* message, long* result)
|
||||
EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
|
||||
|
||||
return new EditorQtApplicationMac(argc, argv);
|
||||
}
|
||||
|
||||
bool EditorQtApplicationMac::nativeEventFilter(const QByteArray& eventType, void* message, long* result)
|
||||
{
|
||||
NSEvent* event = (NSEvent*)message;
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../Core/QtEditorApplication_mac.mm
|
||||
Editor/Core/QtEditorApplication_mac.mm
|
||||
../../LogFile_mac.mm
|
||||
../../WindowObserver_mac.h
|
||||
../../WindowObserver_mac.mm
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "QtEditorApplication_windows.h"
|
||||
|
||||
// Qt
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QScopedValueRollback>
|
||||
#include <QToolBar>
|
||||
#include <QLoggingCategory>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||
|
||||
// AzQtComponents
|
||||
#include <AzQtComponents/Components/Titlebar.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
|
||||
// AzFramework
|
||||
#include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
|
||||
{
|
||||
return new EditorQtApplicationWindows(argc, argv);
|
||||
}
|
||||
|
||||
bool EditorQtApplicationWindows::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long* result)
|
||||
{
|
||||
MSG* msg = (MSG*)message;
|
||||
|
||||
if (msg->message == WM_MOVING || msg->message == WM_SIZING)
|
||||
{
|
||||
m_isMovingOrResizing = true;
|
||||
}
|
||||
else if (msg->message == WM_EXITSIZEMOVE)
|
||||
{
|
||||
m_isMovingOrResizing = false;
|
||||
}
|
||||
|
||||
// Prevent the user from being able to move the window in game mode.
|
||||
// This is done during the hit test phase to bypass the native window move messages. If the window
|
||||
// decoration wrapper title bar contains the cursor, set the result to HTCLIENT instead of
|
||||
// HTCAPTION.
|
||||
if (msg->message == WM_NCHITTEST && GetIEditor()->IsInGameMode())
|
||||
{
|
||||
const LRESULT defWinProcResult = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
||||
if (defWinProcResult == 1)
|
||||
{
|
||||
if (QWidget* widget = QWidget::find((WId)msg->hwnd))
|
||||
{
|
||||
if (auto wrapper = qobject_cast<const AzQtComponents::WindowDecorationWrapper*>(widget))
|
||||
{
|
||||
AzQtComponents::TitleBar* titleBar = wrapper->titleBar();
|
||||
const short global_x = static_cast<short>(LOWORD(msg->lParam));
|
||||
const short global_y = static_cast<short>(HIWORD(msg->lParam));
|
||||
|
||||
const QPoint globalPos = QHighDpi::fromNativePixels(QPoint(global_x, global_y), widget->window()->windowHandle());
|
||||
const QPoint local = titleBar->mapFromGlobal(globalPos);
|
||||
if (titleBar->draggableRect().contains(local) && !titleBar->isTopResizeArea(globalPos))
|
||||
{
|
||||
*result = HTCLIENT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system.
|
||||
// These events are only broadcast in game mode. In Editor mode, RenderViewportWidget creates synthetic
|
||||
// keyboard and mouse events via Qt.
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
if (msg->message == WM_INPUT)
|
||||
{
|
||||
UINT rawInputSize;
|
||||
const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
|
||||
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &rawInputSize, rawInputHeaderSize);
|
||||
|
||||
AZStd::array<BYTE, sizeof(RAWINPUT)> rawInputBytesArray;
|
||||
LPBYTE rawInputBytes = rawInputBytesArray.data();
|
||||
|
||||
[[maybe_unused]] const UINT bytesCopied =
|
||||
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize);
|
||||
CRY_ASSERT(bytesCopied == rawInputSize);
|
||||
|
||||
RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes;
|
||||
CRY_ASSERT(rawInput);
|
||||
|
||||
AzFramework::RawInputNotificationBusWindows::Broadcast(
|
||||
&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (msg->message == WM_DEVICECHANGE)
|
||||
{
|
||||
if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED
|
||||
{
|
||||
AzFramework::RawInputNotificationBusWindows::Broadcast(
|
||||
&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EditorQtApplicationWindows::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::Leave:
|
||||
{
|
||||
// if we receive a leave event for a toolbar on Windows
|
||||
// check first whether we really left it. If we didn't: start checking
|
||||
// for the tool bar under the mouse by timer to check when we really left.
|
||||
// Synthesize a new leave event then. Workaround for LY-69788
|
||||
auto toolBarAt = [](const QPoint& pos) -> QToolBar*
|
||||
{
|
||||
QWidget* widget = qApp->widgetAt(pos);
|
||||
while (widget != nullptr)
|
||||
{
|
||||
if (QToolBar* tb = qobject_cast<QToolBar*>(widget))
|
||||
{
|
||||
return tb;
|
||||
}
|
||||
widget = widget->parentWidget();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (object == toolBarAt(QCursor::pos()))
|
||||
{
|
||||
QTimer* t = new QTimer(object);
|
||||
t->start(100);
|
||||
connect(
|
||||
t, &QTimer::timeout, object,
|
||||
[t, object, toolBarAt]()
|
||||
{
|
||||
if (object != toolBarAt(QCursor::pos()))
|
||||
{
|
||||
QEvent event(QEvent::Leave);
|
||||
qApp->sendEvent(object, &event);
|
||||
t->deleteLater();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EditorQtApplication::eventFilter(object, event);
|
||||
}
|
||||
} // namespace Editor
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Editor/Core/QtEditorApplication.h>
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
class EditorQtApplicationWindows : public EditorQtApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EditorQtApplicationWindows(int& argc, char** argv)
|
||||
: EditorQtApplication(argc, argv)
|
||||
{
|
||||
}
|
||||
|
||||
// QAbstractNativeEventFilter:
|
||||
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
|
||||
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
};
|
||||
} // namespace Editor
|
||||
@@ -7,5 +7,6 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Editor/Core/QtEditorApplication_windows.cpp
|
||||
Util/Mailer_Windows.cpp
|
||||
)
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace AZ
|
||||
else if (info.m_status == AzToolsFramework::SourceControlStatus::SCS_ProviderIsDown)
|
||||
{
|
||||
message = "Failed to put entries/dependencies into source control as the provider is not available.\n";
|
||||
reportAsWarning = true;
|
||||
}
|
||||
else if (info.m_status == AzToolsFramework::SourceControlStatus::SCS_CertificateInvalid)
|
||||
{
|
||||
|
||||
@@ -34,11 +34,12 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
|
||||
m_ui->setupUi(this);
|
||||
|
||||
s_pLogoWindow = this;
|
||||
setFixedSize(QSize(600, 300));
|
||||
setFixedSize(QSize(m_enforcedWidth, m_enforcedHeight));
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
|
||||
// Prepare background image
|
||||
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
|
||||
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
|
||||
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
|
||||
screen(),
|
||||
QSize(m_enforcedWidth, m_enforcedHeight),
|
||||
Qt::IgnoreAspectRatio,
|
||||
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
QScopedPointer<Ui::StartupLogoDialog> m_ui;
|
||||
|
||||
QPixmap m_backgroundImage;
|
||||
const int m_enforcedWidth = 600;
|
||||
const int m_enforcedHeight = 300;
|
||||
const int m_enforcedWidth = 668;
|
||||
const int m_enforcedHeight = 368;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/StartupLogoDialog">
|
||||
<file>o3de_logo.svg</file>
|
||||
<file>splashscreen_background_developer_preview.jpg</file>
|
||||
<file>splashscreen_background_2021_11.jpg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -6,13 +6,22 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>300</height>
|
||||
<width>668</width>
|
||||
<height>368</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>42</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>42</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
<number>42</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>10</number>
|
||||
@@ -29,7 +38,7 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<width>300</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
@@ -53,7 +62,7 @@
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>28</number>
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>24</number>
|
||||
@@ -94,7 +103,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Developer Preview</string>
|
||||
<string>General Availability</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -153,20 +162,28 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>290</width>
|
||||
<height>0</height>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>290</width>
|
||||
<height>16777215</height>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Starting Editor...</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -330,8 +330,6 @@ set(FILES
|
||||
Commands/CommandManager.h
|
||||
Controls/BitmapToolTip.cpp
|
||||
Controls/BitmapToolTip.h
|
||||
Controls/ColorGradientCtrl.cpp
|
||||
Controls/ColorGradientCtrl.h
|
||||
Controls/ConsoleSCB.cpp
|
||||
Controls/ConsoleSCB.h
|
||||
Controls/ConsoleSCB.ui
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ffcb7614bed0790bf58a2bb7b2d70958289cb2edf562acc8fc841f4c50a55445
|
||||
size 2974586
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7105ec99477f124a8ac8d588f2dfc4ee7bb54f39386c8131b7703c86754c0cb8
|
||||
size 248690
|
||||
@@ -577,7 +577,9 @@ namespace AZ
|
||||
}
|
||||
|
||||
azstrcat(lines[i], AZ_ARRAY_SIZE(lines[i]), "\n");
|
||||
AZ_Printf(window, "%s", lines[i]); // feed back into the trace system so that listeners can get it.
|
||||
// Use Output instead of AZ_Printf to be consistent with the exception output code and avoid
|
||||
// this accidentally being suppressed as a normal message
|
||||
Output(window, lines[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/Json/JsonImporter.h>
|
||||
#include <AzCore/Serialization/Json/JsonUtils.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
JsonSerializationResult::ResultCode JsonImportResolver::ResolveNestedImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, ImportPathStack& importPathStack,
|
||||
JsonImportSettings& settings, const AZ::IO::FixedMaxPath& importPath, StackedString& element)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
for (auto& path : importPathStack)
|
||||
{
|
||||
if (importPath == path)
|
||||
{
|
||||
return settings.m_reporting(
|
||||
AZStd::string::format("'%s' was already imported in this chain. This indicates a cyclic dependency.", importPath.c_str()),
|
||||
ResultCode(Tasks::Import, Outcomes::Catastrophic), element);
|
||||
}
|
||||
}
|
||||
|
||||
importPathStack.push_back(importPath);
|
||||
AZ::StackedString importElement(AZ::StackedString::Format::JsonPointer);
|
||||
JsonImportSettings nestedImportSettings;
|
||||
nestedImportSettings.m_importer = settings.m_importer;
|
||||
nestedImportSettings.m_reporting = settings.m_reporting;
|
||||
nestedImportSettings.m_resolveFlags = ImportTracking::Dependencies;
|
||||
ResultCode result = ResolveImports(jsonDoc, allocator, importPathStack, nestedImportSettings, importElement);
|
||||
importPathStack.pop_back();
|
||||
|
||||
if (result.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonImportResolver::ResolveImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, ImportPathStack& importPathStack,
|
||||
JsonImportSettings& settings, StackedString& element)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (jsonDoc.IsObject())
|
||||
{
|
||||
for (auto& field : jsonDoc.GetObject())
|
||||
{
|
||||
if(strncmp(field.name.GetString(), JsonSerialization::ImportDirectiveIdentifier, field.name.GetStringLength()) == 0)
|
||||
{
|
||||
const rapidjson::Value& importDirective = field.value;
|
||||
AZ::IO::FixedMaxPath importAbsPath = importPathStack.back();
|
||||
importAbsPath.RemoveFilename();
|
||||
AZStd::string importName;
|
||||
if (importDirective.IsObject())
|
||||
{
|
||||
auto filenameField = importDirective.FindMember("filename");
|
||||
if (filenameField != importDirective.MemberEnd())
|
||||
{
|
||||
importName = AZStd::string(filenameField->value.GetString(), filenameField->value.GetStringLength());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
importName = AZStd::string(importDirective.GetString(), importDirective.GetStringLength());
|
||||
}
|
||||
importAbsPath.Append(importName);
|
||||
|
||||
rapidjson::Value patch;
|
||||
ResultCode resolveResult = settings.m_importer->ResolveImport(&jsonDoc, patch, importDirective, importAbsPath, allocator);
|
||||
if (resolveResult.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return resolveResult;
|
||||
}
|
||||
|
||||
if ((settings.m_resolveFlags & ImportTracking::Imports) == ImportTracking::Imports)
|
||||
{
|
||||
rapidjson::Pointer path(element.Get().data(), element.Get().size());
|
||||
settings.m_importer->AddImportDirective(path, importName);
|
||||
}
|
||||
if ((settings.m_resolveFlags & ImportTracking::Dependencies) == ImportTracking::Dependencies)
|
||||
{
|
||||
settings.m_importer->AddImportedFile(importAbsPath.String());
|
||||
}
|
||||
|
||||
ResultCode result = ResolveNestedImports(jsonDoc, allocator, importPathStack, settings, importAbsPath, element);
|
||||
if (result.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
settings.m_importer->ApplyPatch(jsonDoc, patch, allocator);
|
||||
}
|
||||
else if (field.value.IsObject() || field.value.IsArray())
|
||||
{
|
||||
ScopedStackedString entryName(element, AZStd::string_view(field.name.GetString(), field.name.GetStringLength()));
|
||||
ResultCode result = ResolveImports(field.value, allocator, importPathStack, settings, element);
|
||||
if (result.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(jsonDoc.IsArray())
|
||||
{
|
||||
int index = 0;
|
||||
for (rapidjson::Value::ValueIterator elem = jsonDoc.Begin(); elem != jsonDoc.End(); ++elem, ++index)
|
||||
{
|
||||
if (!elem->IsObject() && !elem->IsArray())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ScopedStackedString entryName(element, index);
|
||||
ResultCode result = ResolveImports(*elem, allocator, importPathStack, settings, element);
|
||||
if (result.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonImportResolver::RestoreImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (jsonDoc.IsObject() || jsonDoc.IsArray())
|
||||
{
|
||||
const BaseJsonImporter::ImportDirectivesList& importDirectives = settings.m_importer->GetImportDirectives();
|
||||
for (auto& import : importDirectives)
|
||||
{
|
||||
rapidjson::Pointer importPtr = import.first;
|
||||
rapidjson::Value* currentValue = importPtr.Get(jsonDoc);
|
||||
|
||||
rapidjson::Value importedValue(rapidjson::kObjectType);
|
||||
importedValue.AddMember(rapidjson::StringRef(JsonSerialization::ImportDirectiveIdentifier), rapidjson::StringRef(import.second.c_str()), allocator);
|
||||
ResultCode resolveResult = JsonSerialization::ResolveImports(importedValue, allocator, settings);
|
||||
if (resolveResult.GetOutcome() == Outcomes::Catastrophic)
|
||||
{
|
||||
return resolveResult;
|
||||
}
|
||||
|
||||
rapidjson::Value patch;
|
||||
settings.m_importer->CreatePatch(patch, importedValue, *currentValue, allocator);
|
||||
settings.m_importer->RestoreImport(currentValue, patch, allocator, import.second);
|
||||
}
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode BaseJsonImporter::ResolveImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, const rapidjson::Value& importDirective,
|
||||
const AZ::IO::FixedMaxPath& importedFilePath, rapidjson::Document::AllocatorType& allocator)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
auto importedObject = JsonSerializationUtils::ReadJsonFile(importedFilePath.Native());
|
||||
if (importedObject.IsSuccess())
|
||||
{
|
||||
rapidjson::Value& importedDoc = importedObject.GetValue();
|
||||
|
||||
if (importDirective.IsObject())
|
||||
{
|
||||
auto patchField = importDirective.FindMember("patch");
|
||||
if (patchField != importDirective.MemberEnd())
|
||||
{
|
||||
patch.CopyFrom(patchField->value, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
importPtr->CopyFrom(importedDoc, allocator);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResultCode(Tasks::Import, Outcomes::Catastrophic);
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode BaseJsonImporter::RestoreImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator, const AZStd::string& importFilename)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
importPtr->SetObject();
|
||||
if ((patch.IsObject() && patch.MemberCount() > 0) || (patch.IsArray() && !patch.Empty()))
|
||||
{
|
||||
rapidjson::Value importDirective(rapidjson::kObjectType);
|
||||
importDirective.AddMember(rapidjson::StringRef("filename"), rapidjson::StringRef(importFilename.c_str()), allocator);
|
||||
importDirective.AddMember(rapidjson::StringRef("patch"), patch, allocator);
|
||||
importPtr->AddMember(rapidjson::StringRef(JsonSerialization::ImportDirectiveIdentifier), importDirective, allocator);
|
||||
}
|
||||
else
|
||||
{
|
||||
importPtr->AddMember(rapidjson::StringRef(JsonSerialization::ImportDirectiveIdentifier), rapidjson::StringRef(importFilename.c_str()), allocator);
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode BaseJsonImporter::ApplyPatch(rapidjson::Value& target,
|
||||
const rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if ((patch.IsObject() && patch.MemberCount() > 0) || (patch.IsArray() && !patch.Empty()))
|
||||
{
|
||||
return AZ::JsonSerialization::ApplyPatch(target, allocator, patch, JsonMergeApproach::JsonMergePatch);
|
||||
}
|
||||
|
||||
return ResultCode(Tasks::Import, Outcomes::Success);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode BaseJsonImporter::CreatePatch(rapidjson::Value& patch,
|
||||
const rapidjson::Value& source, const rapidjson::Value& target,
|
||||
rapidjson::Document::AllocatorType& allocator)
|
||||
{
|
||||
return JsonSerialization::CreatePatch(patch, allocator, source, target, JsonMergeApproach::JsonMergePatch);
|
||||
}
|
||||
|
||||
void BaseJsonImporter::AddImportDirective(const rapidjson::Pointer& jsonPtr, AZStd::string importFile)
|
||||
{
|
||||
m_importDirectives.emplace_back(jsonPtr, AZStd::move(importFile));
|
||||
}
|
||||
|
||||
void BaseJsonImporter::AddImportedFile(AZStd::string importedFile)
|
||||
{
|
||||
m_importedFiles.insert(AZStd::move(importedFile));
|
||||
}
|
||||
|
||||
const BaseJsonImporter::ImportDirectivesList& BaseJsonImporter::GetImportDirectives()
|
||||
{
|
||||
return m_importDirectives;
|
||||
}
|
||||
|
||||
const BaseJsonImporter::ImportedFilesList& BaseJsonImporter::GetImportedFiles()
|
||||
{
|
||||
return m_importedFiles;
|
||||
}
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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/IO/Path/Path.h>
|
||||
#include <AzCore/JSON/document.h>
|
||||
#include <AzCore/JSON/pointer.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
#include <AzCore/Serialization/Json/StackedString.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
struct JsonImportSettings;
|
||||
|
||||
class BaseJsonImporter
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(BaseJsonImporter, "{7B225807-7B43-430F-8B11-C794DCF5ACA5}");
|
||||
|
||||
using ImportDirectivesList = AZStd::vector<AZStd::pair<rapidjson::Pointer, AZStd::string>>;
|
||||
using ImportedFilesList = AZStd::unordered_set<AZStd::string>;
|
||||
|
||||
virtual JsonSerializationResult::ResultCode ResolveImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, const rapidjson::Value& importDirective,
|
||||
const AZ::IO::FixedMaxPath& importedFilePath, rapidjson::Document::AllocatorType& allocator);
|
||||
|
||||
virtual JsonSerializationResult::ResultCode RestoreImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator,
|
||||
const AZStd::string& importFilename);
|
||||
|
||||
virtual JsonSerializationResult::ResultCode ApplyPatch(rapidjson::Value& target,
|
||||
const rapidjson::Value& patch, rapidjson::Document::AllocatorType& allocator);
|
||||
|
||||
virtual JsonSerializationResult::ResultCode CreatePatch(rapidjson::Value& patch,
|
||||
const rapidjson::Value& source, const rapidjson::Value& target,
|
||||
rapidjson::Document::AllocatorType& allocator);
|
||||
|
||||
void AddImportDirective(const rapidjson::Pointer& jsonPtr, AZStd::string importFile);
|
||||
const ImportDirectivesList& GetImportDirectives();
|
||||
|
||||
void AddImportedFile(AZStd::string importedFile);
|
||||
const ImportedFilesList& GetImportedFiles();
|
||||
|
||||
virtual ~BaseJsonImporter() = default;
|
||||
|
||||
protected:
|
||||
|
||||
ImportDirectivesList m_importDirectives;
|
||||
ImportedFilesList m_importedFiles;
|
||||
};
|
||||
|
||||
enum class ImportTracking : AZ::u8
|
||||
{
|
||||
None = 0,
|
||||
Dependencies = (1<<0),
|
||||
Imports = (1<<1),
|
||||
All = (Dependencies | Imports)
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(ImportTracking);
|
||||
|
||||
class JsonImportResolver final
|
||||
{
|
||||
public:
|
||||
|
||||
using ImportPathStack = AZStd::vector<AZ::IO::FixedMaxPath>;
|
||||
|
||||
JsonImportResolver() = delete;
|
||||
JsonImportResolver& operator=(const JsonImportResolver& rhs) = delete;
|
||||
JsonImportResolver& operator=(JsonImportResolver&& rhs) = delete;
|
||||
JsonImportResolver(const JsonImportResolver& rhs) = delete;
|
||||
JsonImportResolver(JsonImportResolver&& rhs) = delete;
|
||||
~JsonImportResolver() = delete;
|
||||
|
||||
static JsonSerializationResult::ResultCode ResolveImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, ImportPathStack& importPathStack,
|
||||
JsonImportSettings& settings, StackedString& element);
|
||||
|
||||
static JsonSerializationResult::ResultCode RestoreImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings);
|
||||
|
||||
private:
|
||||
|
||||
static JsonSerializationResult::ResultCode ResolveNestedImports(rapidjson::Value& jsonDoc,
|
||||
rapidjson::Document::AllocatorType& allocator, ImportPathStack& importPathStack,
|
||||
JsonImportSettings& settings, const AZ::IO::FixedMaxPath& importPath, StackedString& element);
|
||||
};
|
||||
|
||||
|
||||
struct JsonImportSettings final
|
||||
{
|
||||
JsonSerializationResult::JsonIssueCallback m_reporting;
|
||||
|
||||
BaseJsonImporter* m_importer = nullptr;
|
||||
|
||||
ImportTracking m_resolveFlags = ImportTracking::All;
|
||||
|
||||
AZ::IO::FixedMaxPath m_loadedJsonPath;
|
||||
};
|
||||
} // namespace AZ
|
||||
@@ -706,7 +706,7 @@ namespace AZ
|
||||
rapidjson::Value(rapidjson::kNullType), field.value, element, settings);
|
||||
}
|
||||
|
||||
if (result.GetOutcome() == Outcomes::Success)
|
||||
if (result.GetOutcome() == Outcomes::Success || result.GetOutcome() == Outcomes::PartialDefaults)
|
||||
{
|
||||
rapidjson::Value name;
|
||||
name.CopyFrom(field.name, allocator, true);
|
||||
@@ -717,6 +717,10 @@ namespace AZ
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultCode.Combine(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Do an extra pass to find all the fields that are removed.
|
||||
@@ -751,7 +755,7 @@ namespace AZ
|
||||
rapidjson::Value value;
|
||||
ResultCode result = CreateMergePatchInternal(value, allocator,
|
||||
rapidjson::Value(rapidjson::kNullType), field.value, element, settings);
|
||||
if (result.GetOutcome() == Outcomes::Success)
|
||||
if (result.GetOutcome() == Outcomes::Success || result.GetOutcome() == Outcomes::PartialDefaults)
|
||||
{
|
||||
rapidjson::Value name;
|
||||
name.CopyFrom(field.name, allocator, true);
|
||||
@@ -762,11 +766,20 @@ namespace AZ
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultCode.Combine(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (target.MemberCount() == 0)
|
||||
{
|
||||
resultCode.Combine(settings.m_reporting("Added empty object to JSON Merge Patch.",
|
||||
ResultCode(Tasks::CreatePatch, Outcomes::Success), element));
|
||||
}
|
||||
}
|
||||
|
||||
patch = AZStd::move(resultValue);
|
||||
resultCode.Combine(ResultCode(Tasks::CreatePatch, Outcomes::Success));
|
||||
return resultCode;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonDeserializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonImporter.h>
|
||||
#include <AzCore/Serialization/Json/JsonMerger.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializer.h>
|
||||
@@ -19,11 +20,6 @@
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
const char* JsonSerialization::TypeIdFieldIdentifier = "$type";
|
||||
const char* JsonSerialization::DefaultStringIdentifier = "{}";
|
||||
const char* JsonSerialization::KeyFieldIdentifier = "Key";
|
||||
const char* JsonSerialization::ValueFieldIdentifier = "Value";
|
||||
|
||||
namespace JsonSerializationInternal
|
||||
{
|
||||
template<typename T>
|
||||
@@ -394,6 +390,60 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonSerialization::ResolveImports(
|
||||
rapidjson::Value& jsonDoc, rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (settings.m_importer == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Importer object needs to be provided");
|
||||
return ResultCode(Tasks::Import, Outcomes::Catastrophic);
|
||||
}
|
||||
|
||||
AZStd::string scratchBuffer;
|
||||
auto issueReportingCallback = [&scratchBuffer](AZStd::string_view message, ResultCode result, AZStd::string_view target) -> ResultCode
|
||||
{
|
||||
return JsonSerialization::DefaultIssueReporter(scratchBuffer, message, result, target);
|
||||
};
|
||||
if (!settings.m_reporting)
|
||||
{
|
||||
settings.m_reporting = issueReportingCallback;
|
||||
}
|
||||
|
||||
JsonImportResolver::ImportPathStack importPathStack;
|
||||
importPathStack.push_back(settings.m_loadedJsonPath);
|
||||
StackedString element(StackedString::Format::JsonPointer);
|
||||
|
||||
return JsonImportResolver::ResolveImports(jsonDoc, allocator, importPathStack, settings, element);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonSerialization::RestoreImports(
|
||||
rapidjson::Value& jsonDoc, rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (settings.m_importer == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Importer object needs to be provided");
|
||||
return ResultCode(Tasks::Import, Outcomes::Catastrophic);
|
||||
}
|
||||
|
||||
AZStd::string scratchBuffer;
|
||||
auto issueReportingCallback = [&scratchBuffer](AZStd::string_view message, ResultCode result, AZStd::string_view target) -> ResultCode
|
||||
{
|
||||
return JsonSerialization::DefaultIssueReporter(scratchBuffer, message, result, target);
|
||||
};
|
||||
if (!settings.m_reporting)
|
||||
{
|
||||
settings.m_reporting = issueReportingCallback;
|
||||
}
|
||||
|
||||
settings.m_resolveFlags = ImportTracking::None;
|
||||
|
||||
return JsonImportResolver::RestoreImports(jsonDoc, allocator, settings);
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonSerialization::DefaultIssueReporter(AZStd::string& scratchBuffer,
|
||||
AZStd::string_view message, JsonSerializationResult::ResultCode result, AZStd::string_view path)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
namespace AZ
|
||||
{
|
||||
class BaseJsonSerializer;
|
||||
|
||||
struct JsonImportSettings;
|
||||
|
||||
enum class JsonMergeApproach
|
||||
{
|
||||
@@ -51,10 +53,11 @@ namespace AZ
|
||||
class JsonSerialization final
|
||||
{
|
||||
public:
|
||||
static const char* TypeIdFieldIdentifier;
|
||||
static const char* DefaultStringIdentifier;
|
||||
static const char* KeyFieldIdentifier;
|
||||
static const char* ValueFieldIdentifier;
|
||||
static constexpr const char* TypeIdFieldIdentifier = "$type";
|
||||
static constexpr const char* DefaultStringIdentifier = "{}";
|
||||
static constexpr const char* KeyFieldIdentifier = "Key";
|
||||
static constexpr const char* ValueFieldIdentifier = "Value";
|
||||
static constexpr const char* ImportDirectiveIdentifier = "$import";
|
||||
|
||||
//! Merges two json values together by applying "patch" to "target" using the selected merge algorithm.
|
||||
//! This version of ApplyPatch is destructive to "target". If the patch can't be correctly applied it will
|
||||
@@ -284,6 +287,22 @@ namespace AZ
|
||||
//! @return An enum containing less, equal or greater. In case of an error, the value for the enum will "error".
|
||||
static JsonSerializerCompareResult Compare(const rapidjson::Value& lhs, const rapidjson::Value& rhs);
|
||||
|
||||
//! Resolves all import directives, including nested imports, in the given document. An importer object needs to be passed
|
||||
//! in through the settings.
|
||||
//! @param jsonDoc The json document in which to resolve imports.
|
||||
//! @param allocator The allocator associated with the json document.
|
||||
//! @param settings Additional settings that control the way the imports are resolved.
|
||||
static JsonSerializationResult::ResultCode ResolveImports(
|
||||
rapidjson::Value& jsonDoc, rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings);
|
||||
|
||||
//! Restores all import directives that were present in the json document. The same importer object that was
|
||||
//! passed into ResolveImports through the settings needs to be passed here through settings as well.
|
||||
//! @param jsonDoc The json document in which to restore imports.
|
||||
//! @param allocator The allocator associated with the json document.
|
||||
//! @param settings Additional settings that control the way the imports are restored.
|
||||
static JsonSerializationResult::ResultCode RestoreImports(
|
||||
rapidjson::Value& jsonDoc, rapidjson::Document::AllocatorType& allocator, JsonImportSettings& settings);
|
||||
|
||||
private:
|
||||
JsonSerialization() = delete;
|
||||
~JsonSerialization() = delete;
|
||||
|
||||
@@ -69,6 +69,9 @@ namespace AZ
|
||||
case Tasks::CreatePatch:
|
||||
target.append("a create patch operation ");
|
||||
break;
|
||||
case Tasks::Import:
|
||||
target.append("an import operation");
|
||||
break;
|
||||
default:
|
||||
target.append("an unknown operation ");
|
||||
break;
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace AZ
|
||||
ReadField, //!< Task to read a field from JSON to a value.
|
||||
WriteValue, //!< Task to write a value to a JSON field.
|
||||
Merge, //!< Task to merge two JSON values/documents together.
|
||||
CreatePatch //!< Task to create a patch to transform one value/document to another.
|
||||
CreatePatch, //!< Task to create a patch to transform one value/document to another.
|
||||
Import //!< Task to import a JSON document.
|
||||
};
|
||||
|
||||
//! Describes how the task was processed.
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace AZ::Utils
|
||||
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath)
|
||||
{
|
||||
AZ::IO::FixedMaxPath filePathFixed = filePath; // Because FileIOStream requires a null-terminated string
|
||||
AZ::IO::FileIOStream stream(filePathFixed.c_str(), AZ::IO::OpenMode::ModeWrite);
|
||||
AZ::IO::FileIOStream stream(filePathFixed.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath);
|
||||
|
||||
bool success = false;
|
||||
|
||||
|
||||
@@ -522,6 +522,8 @@ set(FILES
|
||||
Serialization/Json/IntSerializer.cpp
|
||||
Serialization/Json/JsonDeserializer.h
|
||||
Serialization/Json/JsonDeserializer.cpp
|
||||
Serialization/Json/JsonImporter.cpp
|
||||
Serialization/Json/JsonImporter.h
|
||||
Serialization/Json/JsonMerger.h
|
||||
Serialization/Json/JsonMerger.cpp
|
||||
Serialization/Json/JsonSerialization.h
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/Json/JsonImporter.h>
|
||||
#include <AzCore/Serialization/Json/JsonUtils.h>
|
||||
#include <Tests/Serialization/Json/JsonSerializationTests.h>
|
||||
|
||||
namespace JsonSerializationTests
|
||||
{
|
||||
class JsonImportingTests;
|
||||
|
||||
class JsonImporterCustom
|
||||
: public AZ::BaseJsonImporter
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(JsonImporterCustom, "{003F5896-71E0-4A50-A14F-08C319B06AD0}");
|
||||
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode ResolveImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, const rapidjson::Value& importDirective,
|
||||
const AZ::IO::FixedMaxPath& importedFilePath, rapidjson::Document::AllocatorType& allocator) override;
|
||||
|
||||
JsonImporterCustom(JsonImportingTests* tests)
|
||||
{
|
||||
testClass = tests;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonImportingTests* testClass;
|
||||
};
|
||||
|
||||
class JsonImportingTests
|
||||
: public BaseJsonSerializerFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
BaseJsonSerializerFixture::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
BaseJsonSerializerFixture::TearDown();
|
||||
}
|
||||
|
||||
void GetTestDocument(const AZStd::string& docName, rapidjson::Document& out)
|
||||
{
|
||||
const char *objectJson = R"({
|
||||
"field_1" : "value_1",
|
||||
"field_2" : "value_2",
|
||||
"field_3" : "value_3"
|
||||
})";
|
||||
|
||||
const char *arrayJson = R"([
|
||||
{ "element_1" : "value_1" },
|
||||
{ "element_2" : "value_2" },
|
||||
{ "element_3" : "value_3" }
|
||||
])";
|
||||
|
||||
const char *nestedImportJson = R"({
|
||||
"desc" : "Nested Import",
|
||||
"obj" : {"$import" : "object.json"}
|
||||
})";
|
||||
|
||||
const char *nestedImportCycle1Json = R"({
|
||||
"desc" : "Nested Import Cycle 1",
|
||||
"obj" : {"$import" : "nested_import_c2.json"}
|
||||
})";
|
||||
|
||||
const char *nestedImportCycle2Json = R"({
|
||||
"desc" : "Nested Import Cycle 2",
|
||||
"obj" : {"$import" : "nested_import_c1.json"}
|
||||
})";
|
||||
|
||||
if (docName.compare("object.json") == 0)
|
||||
{
|
||||
out.Parse(objectJson);
|
||||
ASSERT_FALSE(out.HasParseError());
|
||||
}
|
||||
else if (docName.compare("array.json") == 0)
|
||||
{
|
||||
out.Parse(arrayJson);
|
||||
ASSERT_FALSE(out.HasParseError());
|
||||
}
|
||||
else if (docName.compare("nested_import.json") == 0)
|
||||
{
|
||||
out.Parse(nestedImportJson);
|
||||
ASSERT_FALSE(out.HasParseError());
|
||||
}
|
||||
else if (docName.compare("nested_import_c1.json") == 0)
|
||||
{
|
||||
out.Parse(nestedImportCycle1Json);
|
||||
ASSERT_FALSE(out.HasParseError());
|
||||
}
|
||||
else if (docName.compare("nested_import_c2.json") == 0)
|
||||
{
|
||||
out.Parse(nestedImportCycle2Json);
|
||||
ASSERT_FALSE(out.HasParseError());
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void TestImportLoadStore(const char* input, const char* expectedImportedValue)
|
||||
{
|
||||
m_jsonDocument->Parse(input);
|
||||
ASSERT_FALSE(m_jsonDocument->HasParseError());
|
||||
|
||||
JsonImporterCustom* importerObj = new JsonImporterCustom(this);
|
||||
|
||||
rapidjson::Document expectedOutcome;
|
||||
expectedOutcome.Parse(expectedImportedValue);
|
||||
ASSERT_FALSE(expectedOutcome.HasParseError());
|
||||
|
||||
TestResolveImports(importerObj);
|
||||
|
||||
Expect_DocStrEq(m_jsonDocument->GetObject(), expectedOutcome.GetObject());
|
||||
|
||||
rapidjson::Document originalInput;
|
||||
originalInput.Parse(input);
|
||||
ASSERT_FALSE(originalInput.HasParseError());
|
||||
|
||||
TestRestoreImports(importerObj);
|
||||
|
||||
Expect_DocStrEq(m_jsonDocument->GetObject(), originalInput.GetObject());
|
||||
|
||||
m_jsonDocument->SetObject();
|
||||
delete importerObj;
|
||||
}
|
||||
|
||||
void TestImportCycle(const char* input)
|
||||
{
|
||||
m_jsonDocument->Parse(input);
|
||||
ASSERT_FALSE(m_jsonDocument->HasParseError());
|
||||
|
||||
JsonImporterCustom* importerObj = new JsonImporterCustom(this);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result = TestResolveImports(importerObj);
|
||||
|
||||
EXPECT_EQ(result.GetOutcome(), AZ::JsonSerializationResult::Outcomes::Catastrophic);
|
||||
|
||||
m_jsonDocument->SetObject();
|
||||
delete importerObj;
|
||||
}
|
||||
|
||||
void TestInsertNewImport(const char* input, const char* expectedRestoredValue)
|
||||
{
|
||||
m_jsonDocument->Parse(input);
|
||||
ASSERT_FALSE(m_jsonDocument->HasParseError());
|
||||
|
||||
JsonImporterCustom* importerObj = new JsonImporterCustom(this);
|
||||
|
||||
TestResolveImports(importerObj);
|
||||
|
||||
importerObj->AddImportDirective(rapidjson::Pointer("/object_2"), "object.json");
|
||||
|
||||
rapidjson::Document expectedOutput;
|
||||
expectedOutput.Parse(expectedRestoredValue);
|
||||
ASSERT_FALSE(expectedOutput.HasParseError());
|
||||
|
||||
TestRestoreImports(importerObj);
|
||||
|
||||
Expect_DocStrEq(m_jsonDocument->GetObject(), expectedOutput.GetObject());
|
||||
|
||||
m_jsonDocument->SetObject();
|
||||
delete importerObj;
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode TestResolveImports(JsonImporterCustom* importerObj)
|
||||
{
|
||||
AZ::JsonImportSettings settings;
|
||||
settings.m_importer = importerObj;
|
||||
|
||||
return AZ::JsonSerialization::ResolveImports(m_jsonDocument->GetObject(), m_jsonDocument->GetAllocator(), settings);
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode TestRestoreImports(JsonImporterCustom* importerObj)
|
||||
{
|
||||
AZ::JsonImportSettings settings;
|
||||
settings.m_importer = importerObj;
|
||||
|
||||
return AZ::JsonSerialization::RestoreImports(m_jsonDocument->GetObject(), m_jsonDocument->GetAllocator(), settings);
|
||||
}
|
||||
};
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode JsonImporterCustom::ResolveImport(rapidjson::Value* importPtr,
|
||||
rapidjson::Value& patch, const rapidjson::Value& importDirective, const AZ::IO::FixedMaxPath& importedFilePath,
|
||||
rapidjson::Document::AllocatorType& allocator)
|
||||
{
|
||||
AZ::JsonSerializationResult::ResultCode resultCode(AZ::JsonSerializationResult::Tasks::Import);
|
||||
|
||||
rapidjson::Document importedDoc;
|
||||
testClass->GetTestDocument(importedFilePath.String(), importedDoc);
|
||||
|
||||
if (importDirective.IsObject())
|
||||
{
|
||||
auto patchField = importDirective.FindMember("patch");
|
||||
if (patchField != importDirective.MemberEnd())
|
||||
{
|
||||
patch.CopyFrom(patchField->value, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
importPtr->CopyFrom(importedDoc, allocator);
|
||||
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
// Test Cases
|
||||
|
||||
TEST_F(JsonImportingTests, ImportSimpleObjectTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object": {"$import" : "object.json"}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object": {
|
||||
"field_1" : "value_1",
|
||||
"field_2" : "value_2",
|
||||
"field_3" : "value_3"
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, ImportSimpleObjectPatchTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object": {
|
||||
"$import" : {
|
||||
"filename" : "object.json",
|
||||
"patch" : { "field_2" : "patched_value" }
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object": {
|
||||
"field_1" : "value_1",
|
||||
"field_2" : "patched_value",
|
||||
"field_3" : "value_3"
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, ImportSimpleArrayTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "simple_array_import",
|
||||
"object": {"$import" : "array.json"}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "simple_array_import",
|
||||
"object": [
|
||||
{ "element_1" : "value_1" },
|
||||
{ "element_2" : "value_2" },
|
||||
{ "element_3" : "value_3" }
|
||||
]
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, ImportSimpleArrayPatchTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "simple_array_import",
|
||||
"object": {
|
||||
"$import" : {
|
||||
"filename" : "array.json",
|
||||
"patch" : [ { "element_1" : "patched_value" } ]
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "simple_array_import",
|
||||
"object": [
|
||||
{ "element_1" : "patched_value" }
|
||||
]
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, NestedImportTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "nested_import",
|
||||
"object": {"$import" : "nested_import.json"}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "nested_import",
|
||||
"object": {
|
||||
"desc" : "Nested Import",
|
||||
"obj" : {
|
||||
"field_1" : "value_1",
|
||||
"field_2" : "value_2",
|
||||
"field_3" : "value_3"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, NestedImportPatchTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "nested_import",
|
||||
"object": {
|
||||
"$import" : {
|
||||
"filename" : "nested_import.json",
|
||||
"patch" : { "obj" : { "field_3" : "patched_value" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "nested_import",
|
||||
"object": {
|
||||
"desc" : "Nested Import",
|
||||
"obj" : {
|
||||
"field_1" : "value_1",
|
||||
"field_2" : "value_2",
|
||||
"field_3" : "patched_value"
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportLoadStore(inputFile, expectedOutput);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, NestedImportCycleTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "nested_import_cycle",
|
||||
"object": {"$import" : "nested_import_c1.json"}
|
||||
}
|
||||
)";
|
||||
|
||||
TestImportCycle(inputFile);
|
||||
}
|
||||
|
||||
TEST_F(JsonImportingTests, InsertNewImportTest)
|
||||
{
|
||||
const char* inputFile = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object_1": {"$import" : "object.json"},
|
||||
"object_2": {
|
||||
"field_1" : "other_value",
|
||||
"field_2" : "value_2",
|
||||
"field_3" : "value_3"
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
const char* expectedOutput = R"(
|
||||
{
|
||||
"name" : "simple_object_import",
|
||||
"object_1": {"$import" : "object.json"},
|
||||
"object_2": {
|
||||
"$import" : {
|
||||
"filename" : "object.json",
|
||||
"patch" : { "field_1" : "other_value" }
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
TestInsertNewImport(inputFile, expectedOutput);
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,7 @@ set(FILES
|
||||
Serialization/Json/TestCases_Classes.cpp
|
||||
Serialization/Json/TestCases_Compare.cpp
|
||||
Serialization/Json/TestCases_Enum.cpp
|
||||
Serialization/Json/TestCases_Importing.cpp
|
||||
Serialization/Json/TestCases_Patching.cpp
|
||||
Serialization/Json/TestCases_Pointers.h
|
||||
Serialization/Json/TestCases_Pointers.cpp
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <AzFramework/Script/ScriptComponent.h>
|
||||
#include <AzFramework/Spawnable/SpawnableSystemComponent.h>
|
||||
#include <AzFramework/StreamingInstall/StreamingInstall.h>
|
||||
#include <AzFramework/SurfaceData/SurfaceData.h>
|
||||
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
|
||||
#include <AzFramework/Viewport/CameraState.h>
|
||||
#include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h>
|
||||
@@ -278,6 +279,8 @@ namespace AzFramework
|
||||
AzFramework::RemoteStorageDriveConfig::Reflect(context);
|
||||
|
||||
Physics::ReflectionUtils::ReflectPhysicsApi(context);
|
||||
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
|
||||
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
|
||||
AzFramework::Terrain::TerrainDataRequests::Reflect(context);
|
||||
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace AzFramework
|
||||
class IMatchmakingAsyncRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ISessionAsyncRequests, "{53513480-2D02-493C-B44E-96AA27F42429}");
|
||||
AZ_RTTI(IMatchmakingAsyncRequests, "{53513480-2D02-493C-B44E-96AA27F42429}");
|
||||
|
||||
IMatchmakingAsyncRequests() = default;
|
||||
virtual ~IMatchmakingAsyncRequests() = default;
|
||||
@@ -60,4 +60,31 @@ namespace AzFramework
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmakingAsync(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
|
||||
//! MatchmakingAsyncRequestNotifications
|
||||
//! The notifications correspond to matchmaking async requests
|
||||
class MatchmakingAsyncRequestNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
|
||||
virtual void OnAcceptMatchAsyncComplete() = 0;
|
||||
|
||||
// OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
|
||||
// @param matchmakingTicketId The unique identifier for the matchmaking ticket
|
||||
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
|
||||
|
||||
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
virtual void OnStopMatchmakingAsyncComplete() = 0;
|
||||
};
|
||||
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -13,36 +13,10 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! MatchmakingAsyncRequestNotifications
|
||||
//! The notifications correspond to matchmaking async requests
|
||||
class MatchmakingAsyncRequestNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
|
||||
virtual void OnAcceptMatchAsyncComplete() = 0;
|
||||
|
||||
// OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
|
||||
// @param matchmakingTicketId The unique identifier for the matchmaking ticket
|
||||
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
|
||||
|
||||
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
virtual void OnStopMatchmakingAsyncComplete() = 0;
|
||||
};
|
||||
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
|
||||
|
||||
//! MatchmakingNotifications
|
||||
//! The matchmaking notifications to listen for performing required operations
|
||||
class MatchAcceptanceNotifications
|
||||
//! based on matchmaking ticket event
|
||||
class MatchmakingNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
@@ -55,8 +29,18 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnMatchAcceptance is fired when DescribeMatchmaking ticket status is REQUIRES_ACCEPTANCE
|
||||
// OnMatchAcceptance is fired when match is found and pending on acceptance
|
||||
// Use this notification to accept found match
|
||||
virtual void OnMatchAcceptance() = 0;
|
||||
|
||||
// OnMatchComplete is fired when match is complete
|
||||
virtual void OnMatchComplete() = 0;
|
||||
|
||||
// OnMatchError is fired when match is processed with error
|
||||
virtual void OnMatchError() = 0;
|
||||
|
||||
// OnMatchFailure is fired when match is failed to complete
|
||||
virtual void OnMatchFailure() = 0;
|
||||
};
|
||||
using MatchAcceptanceNotificationBus = AZ::EBus<MatchAcceptanceNotifications>;
|
||||
using MatchmakingNotificationBus = AZ::EBus<MatchmakingNotifications>;
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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/Math/Vector3.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzFramework/Physics/Material.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
//! The QuadMeshType specifies the property of the heightfield quad.
|
||||
enum class QuadMeshType : uint8_t
|
||||
{
|
||||
SubdivideUpperLeftToBottomRight, //!< Subdivide the quad, from upper left to bottom right |\|, into two triangles.
|
||||
SubdivideBottomLeftToUpperRight, //!< Subdivide the quad, from bottom left to upper right |/|, into two triangles.
|
||||
Hole //!< The quad should be treated as a hole in the heightfield.
|
||||
};
|
||||
|
||||
struct HeightMaterialPoint
|
||||
{
|
||||
float m_height{ 0.0f }; //!< Holds the height of this point in the heightfield relative to the heightfield entity location.
|
||||
QuadMeshType m_quadMeshType{ QuadMeshType::SubdivideUpperLeftToBottomRight }; //!< By default, create two triangles like this |\|, where this point is in the upper left corner.
|
||||
uint8_t m_materialIndex{ 0 }; //!< The surface material index for the upper left corner of this quad.
|
||||
uint16_t m_padding{ 0 }; //!< available for future use.
|
||||
};
|
||||
|
||||
//! An interface to provide heightfield values.
|
||||
class HeightfieldProviderRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
//! Returns the distance between each height in the map.
|
||||
//! @return Vector containing Column Spacing, Rows Spacing.
|
||||
virtual AZ::Vector2 GetHeightfieldGridSpacing() const = 0;
|
||||
|
||||
//! Returns the height field gridsize.
|
||||
//! @param numColumns contains the size of the grid in the x direction.
|
||||
//! @param numRows contains the size of the grid in the y direction.
|
||||
virtual void GetHeightfieldGridSize(int32_t& numColumns, int32_t& numRows) const = 0;
|
||||
|
||||
//! Returns the height field min and max height bounds.
|
||||
//! @param minHeightBounds contains the minimum height that the heightfield can contain.
|
||||
//! @param maxHeightBounds contains the maximum height that the heightfield can contain.
|
||||
virtual void GetHeightfieldHeightBounds(float& minHeightBounds, float& maxHeightBounds) const = 0;
|
||||
|
||||
//! Returns the AABB of the heightfield.
|
||||
//! This is provided separately from the shape AABB because the heightfield might choose to modify the AABB bounds.
|
||||
//! @return AABB of the heightfield.
|
||||
virtual AZ::Aabb GetHeightfieldAabb() const = 0;
|
||||
|
||||
//! Returns the world transform for the heightfield.
|
||||
//! This is provided separately from the entity transform because the heightfield might want to clear out the rotation or scale.
|
||||
//! @return world transform that should be used with the heightfield data.
|
||||
virtual AZ::Transform GetHeightfieldTransform() const = 0;
|
||||
|
||||
//! Returns the list of materials used by the height field.
|
||||
//! @return returns a vector of all materials.
|
||||
virtual AZStd::vector<MaterialId> GetMaterialList() const = 0;
|
||||
|
||||
//! Returns the list of heights used by the height field.
|
||||
//! @return the rows*columns vector of the heights.
|
||||
virtual AZStd::vector<float> GetHeights() const = 0;
|
||||
|
||||
//! Returns the list of heights and materials used by the height field.
|
||||
//! @return the rows*columns vector of the heights and materials.
|
||||
virtual AZStd::vector<Physics::HeightMaterialPoint> GetHeightsAndMaterials() const = 0;
|
||||
};
|
||||
|
||||
using HeightfieldProviderRequestsBus = AZ::EBus<HeightfieldProviderRequests>;
|
||||
|
||||
//! Broadcasts notifications when heightfield data changes - heightfield providers implement HeightfieldRequests bus.
|
||||
class HeightfieldProviderNotifications
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
//! Called whenever the heightfield data changes.
|
||||
//! @param the AABB of the area of data that changed.
|
||||
virtual void OnHeightfieldDataChanged([[maybe_unused]] const AZ::Aabb& dirtyRegion)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
~HeightfieldProviderNotifications() = default;
|
||||
};
|
||||
|
||||
using HeightfieldProviderNotificationBus = AZ::EBus<HeightfieldProviderNotifications>;
|
||||
} // namespace Physics
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 <gmock/gmock.h>
|
||||
|
||||
#include <AzFramework/Physics/HeightfieldProviderBus.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class MockHeightfieldProviderNotificationBusListener
|
||||
: private Physics::HeightfieldProviderNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
MockHeightfieldProviderNotificationBusListener(AZ::EntityId entityid)
|
||||
{
|
||||
Physics::HeightfieldProviderNotificationBus::Handler::BusConnect(entityid);
|
||||
}
|
||||
|
||||
~MockHeightfieldProviderNotificationBusListener()
|
||||
{
|
||||
Physics::HeightfieldProviderNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
MOCK_METHOD1(OnHeightfieldDataChanged, void(const AZ::Aabb&));
|
||||
};
|
||||
} // namespace UnitTest
|
||||
@@ -37,6 +37,7 @@ namespace Physics
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Sphere);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Cylinder);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(PhysicsAsset);
|
||||
REFLECT_SHAPETYPE_ENUM_VALUE(Heightfield);
|
||||
|
||||
#undef REFLECT_SHAPETYPE_ENUM_VALUE
|
||||
}
|
||||
@@ -285,12 +286,17 @@ namespace Physics
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
|
||||
const void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
|
||||
{
|
||||
return m_cachedNativeMesh;
|
||||
}
|
||||
|
||||
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) const
|
||||
void* CookedMeshShapeConfiguration::GetCachedNativeMesh()
|
||||
{
|
||||
return m_cachedNativeMesh;
|
||||
}
|
||||
|
||||
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh)
|
||||
{
|
||||
m_cachedNativeMesh = cachedNativeMesh;
|
||||
}
|
||||
@@ -305,4 +311,131 @@ namespace Physics
|
||||
m_cachedNativeMesh = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext
|
||||
->RegisterGenericType<AZStd::shared_ptr<HeightfieldShapeConfiguration>>();
|
||||
|
||||
serializeContext->Class<HeightfieldShapeConfiguration, ShapeConfiguration>()
|
||||
->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration::~HeightfieldShapeConfiguration()
|
||||
{
|
||||
SetCachedNativeHeightfield(nullptr);
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration::HeightfieldShapeConfiguration(const HeightfieldShapeConfiguration& other)
|
||||
: ShapeConfiguration(other)
|
||||
, m_gridResolution(other.m_gridResolution)
|
||||
, m_numColumns(other.m_numColumns)
|
||||
, m_numRows(other.m_numRows)
|
||||
, m_samples(other.m_samples)
|
||||
, m_minHeightBounds(other.m_minHeightBounds)
|
||||
, m_maxHeightBounds(other.m_maxHeightBounds)
|
||||
, m_cachedNativeHeightfield(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
HeightfieldShapeConfiguration& HeightfieldShapeConfiguration::operator=(const HeightfieldShapeConfiguration& other)
|
||||
{
|
||||
ShapeConfiguration::operator=(other);
|
||||
|
||||
m_gridResolution = other.m_gridResolution;
|
||||
m_numColumns = other.m_numColumns;
|
||||
m_numRows = other.m_numRows;
|
||||
m_samples = other.m_samples;
|
||||
m_minHeightBounds = other.m_minHeightBounds;
|
||||
m_maxHeightBounds = other.m_maxHeightBounds;
|
||||
|
||||
// Prevent raw pointer from being copied
|
||||
m_cachedNativeHeightfield = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const
|
||||
{
|
||||
return m_cachedNativeHeightfield;
|
||||
}
|
||||
|
||||
void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield()
|
||||
{
|
||||
return m_cachedNativeHeightfield;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield)
|
||||
{
|
||||
if (m_cachedNativeHeightfield)
|
||||
{
|
||||
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::ReleaseNativeHeightfieldObject, m_cachedNativeHeightfield);
|
||||
}
|
||||
|
||||
m_cachedNativeHeightfield = cachedNativeHeightfield;
|
||||
}
|
||||
|
||||
AZ::Vector2 HeightfieldShapeConfiguration::GetGridResolution() const
|
||||
{
|
||||
return m_gridResolution;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetGridResolution(const AZ::Vector2& gridResolution)
|
||||
{
|
||||
m_gridResolution = gridResolution;
|
||||
}
|
||||
|
||||
int32_t HeightfieldShapeConfiguration::GetNumColumns() const
|
||||
{
|
||||
return m_numColumns;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetNumColumns(int32_t numColumns)
|
||||
{
|
||||
m_numColumns = numColumns;
|
||||
}
|
||||
|
||||
int32_t HeightfieldShapeConfiguration::GetNumRows() const
|
||||
{
|
||||
return m_numRows;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetNumRows(int32_t numRows)
|
||||
{
|
||||
m_numRows = numRows;
|
||||
}
|
||||
|
||||
const AZStd::vector<Physics::HeightMaterialPoint>& HeightfieldShapeConfiguration::GetSamples() const
|
||||
{
|
||||
return m_samples;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& samples)
|
||||
{
|
||||
m_samples = samples;
|
||||
}
|
||||
|
||||
float HeightfieldShapeConfiguration::GetMinHeightBounds() const
|
||||
{
|
||||
return m_minHeightBounds;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetMinHeightBounds(float minBounds)
|
||||
{
|
||||
m_minHeightBounds = minBounds;
|
||||
}
|
||||
|
||||
float HeightfieldShapeConfiguration::GetMaxHeightBounds() const
|
||||
{
|
||||
return m_maxHeightBounds;
|
||||
}
|
||||
|
||||
void HeightfieldShapeConfiguration::SetMaxHeightBounds(float maxBounds)
|
||||
{
|
||||
m_maxHeightBounds = maxBounds;
|
||||
}
|
||||
} // namespace Physics
|
||||
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzFramework/Physics/HeightfieldProviderBus.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
/// Used to identify shape configuration type from base class.
|
||||
@@ -27,6 +30,7 @@ namespace Physics
|
||||
Native, ///< Native shape configuration if user wishes to bypass generic shape configurations.
|
||||
PhysicsAsset, ///< Shapes configured in the asset.
|
||||
CookedMesh, ///< Stores a blob of mesh data cooked for the specific engine.
|
||||
Heightfield ///< Interacts with the physics system heightfield
|
||||
};
|
||||
|
||||
class ShapeConfiguration
|
||||
@@ -183,8 +187,9 @@ namespace Physics
|
||||
|
||||
MeshType GetMeshType() const;
|
||||
|
||||
void* GetCachedNativeMesh() const;
|
||||
void SetCachedNativeMesh(void* cachedNativeMesh) const;
|
||||
void* GetCachedNativeMesh();
|
||||
const void* GetCachedNativeMesh() const;
|
||||
void SetCachedNativeMesh(void* cachedNativeMesh);
|
||||
|
||||
private:
|
||||
void ReleaseCachedNativeMesh();
|
||||
@@ -193,7 +198,56 @@ namespace Physics
|
||||
MeshType m_type = MeshType::TriangleMesh;
|
||||
|
||||
//! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized.
|
||||
mutable void* m_cachedNativeMesh = nullptr;
|
||||
void* m_cachedNativeMesh = nullptr;
|
||||
};
|
||||
|
||||
class HeightfieldShapeConfiguration
|
||||
: public ShapeConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(HeightfieldShapeConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(HeightfieldShapeConfiguration, "{8DF47C83-D2A9-4E7C-8620-5E173E43C0B3}", ShapeConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
HeightfieldShapeConfiguration() = default;
|
||||
HeightfieldShapeConfiguration(const HeightfieldShapeConfiguration&);
|
||||
HeightfieldShapeConfiguration& operator=(const HeightfieldShapeConfiguration&);
|
||||
~HeightfieldShapeConfiguration();
|
||||
|
||||
ShapeType GetShapeType() const override
|
||||
{
|
||||
return ShapeType::Heightfield;
|
||||
}
|
||||
|
||||
const void* GetCachedNativeHeightfield() const;
|
||||
void* GetCachedNativeHeightfield();
|
||||
void SetCachedNativeHeightfield(void* cachedNativeHeightfield);
|
||||
AZ::Vector2 GetGridResolution() const;
|
||||
void SetGridResolution(const AZ::Vector2& gridSpacing);
|
||||
int32_t GetNumColumns() const;
|
||||
void SetNumColumns(int32_t numColumns);
|
||||
int32_t GetNumRows() const;
|
||||
void SetNumRows(int32_t numRows);
|
||||
const AZStd::vector<Physics::HeightMaterialPoint>& GetSamples() const;
|
||||
void SetSamples(const AZStd::vector<Physics::HeightMaterialPoint>& samples);
|
||||
float GetMinHeightBounds() const;
|
||||
void SetMinHeightBounds(float minBounds);
|
||||
float GetMaxHeightBounds() const;
|
||||
void SetMaxHeightBounds(float maxBounds);
|
||||
|
||||
private:
|
||||
//! The number of meters between each heightfield sample.
|
||||
AZ::Vector2 m_gridResolution{ 1.0f };
|
||||
//! The number of columns in the heightfield sample grid.
|
||||
int32_t m_numColumns{ 0 };
|
||||
//! The number of rows in the heightfield sample grid.
|
||||
int32_t m_numRows{ 0 };
|
||||
//! The minimum and maximum heights that can be used by this heightfield.
|
||||
//! This can be used by the physics system to choose a more optimal heightfield data type internally (ex: int16, uint8)
|
||||
float m_minHeightBounds{AZStd::numeric_limits<float>::lowest()};
|
||||
float m_maxHeightBounds{AZStd::numeric_limits<float>::max()};
|
||||
//! The grid of sample points for the heightfield.
|
||||
AZStd::vector<Physics::HeightMaterialPoint> m_samples;
|
||||
//! An optional storage pointer for the physics system to cache its native heightfield representation.
|
||||
void* m_cachedNativeHeightfield{ nullptr };
|
||||
};
|
||||
} // namespace Physics
|
||||
|
||||
@@ -132,6 +132,10 @@ namespace Physics
|
||||
|
||||
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
|
||||
|
||||
/// Releases the height field object created by the physics backend.
|
||||
/// @param nativeHeightfieldObject Pointer to the height field object.
|
||||
virtual void ReleaseNativeHeightfieldObject(void* nativeHeightfieldObject) = 0;
|
||||
|
||||
/// Releases the mesh object created by the physics backend.
|
||||
/// @param nativeMeshObject Pointer to the mesh object.
|
||||
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace Physics
|
||||
PhysicsAssetShapeConfiguration::Reflect(context);
|
||||
NativeShapeConfiguration::Reflect(context);
|
||||
CookedMeshShapeConfiguration::Reflect(context);
|
||||
HeightfieldShapeConfiguration::Reflect(context);
|
||||
AzPhysics::SystemInterface::Reflect(context);
|
||||
AzPhysics::Scene::Reflect(context);
|
||||
AzPhysics::CollisionLayer::Reflect(context);
|
||||
|
||||
+2
-2
@@ -7,5 +7,5 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Source/AudioEngineWwiseModule_Stub.cpp
|
||||
)
|
||||
Mocks/MockHeightfieldProviderBus.h
|
||||
)
|
||||
@@ -22,7 +22,7 @@ namespace AzFramework
|
||||
AZStd::scoped_ptr<ProcessWatcher> pWatcher(LaunchProcess(processLaunchInfo, communicationType));
|
||||
if (!pWatcher)
|
||||
{
|
||||
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to launch process '%s %s'", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
|
||||
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: Unable to launch process '%s %s'\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -31,7 +31,7 @@ namespace AzFramework
|
||||
ProcessCommunicator* pCommunicator = pWatcher->GetCommunicator();
|
||||
if (!pCommunicator || !pCommunicator->IsValid())
|
||||
{
|
||||
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: No communicator for watcher's process (%s %s)!", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
|
||||
AZ_TracePrintf("Process Watcher", "ProcessWatcher::LaunchProcessAndRetrieveOutput: No communicator for watcher's process (%s %s)!\n", processLaunchInfo.m_processExecutableString.c_str(), processLaunchInfo.m_commandlineParameters.c_str());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/SurfaceData/SurfaceData.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AzFramework::SurfaceData
|
||||
{
|
||||
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SurfaceTagWeight>()
|
||||
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType)
|
||||
->Field("m_weight", &SurfaceTagWeight::m_weight)
|
||||
;
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SurfaceTagWeight>()
|
||||
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
|
||||
->Constructor()
|
||||
->Property("surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType))
|
||||
->Property("weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void SurfacePoint::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SurfacePoint>()
|
||||
->Field("m_position", &SurfacePoint::m_position)
|
||||
->Field("m_normal", &SurfacePoint::m_normal)
|
||||
->Field("m_surfaceTags", &SurfacePoint::m_surfaceTags)
|
||||
;
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SurfacePoint>("AzFramework::SurfaceData::SurfacePoint")
|
||||
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
|
||||
->Constructor()
|
||||
->Property("position", BehaviorValueProperty(&SurfacePoint::m_position))
|
||||
->Property("normal", BehaviorValueProperty(&SurfacePoint::m_normal))
|
||||
->Property("surfaceTags", BehaviorValueProperty(&SurfacePoint::m_surfaceTags))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AzFramework::SurfaceData
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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/Math/Crc.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AzFramework::SurfaceData
|
||||
{
|
||||
namespace Constants
|
||||
{
|
||||
static constexpr const char* s_unassignedTagName = "(unassigned)";
|
||||
}
|
||||
|
||||
struct SurfaceTagWeight
|
||||
{
|
||||
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
|
||||
SurfaceTagWeight() = default;
|
||||
SurfaceTagWeight(AZ::Crc32 surfaceType, float weight)
|
||||
: m_surfaceType(surfaceType)
|
||||
, m_weight(weight)
|
||||
{
|
||||
}
|
||||
|
||||
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
|
||||
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
struct SurfaceTagWeightComparator
|
||||
{
|
||||
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
|
||||
{
|
||||
// Return a deterministic sort order for surface tags from highest to lowest weight, with the surface types sorted
|
||||
// in a predictable order when the weights are equal. The surface type sort order is meaningless since it is sorting CRC
|
||||
// values, it's really just important for it to be stable.
|
||||
// For the floating-point weight comparisons we use exact instead of IsClose value comparisons for a similar reason - we
|
||||
// care about being sorted highest to lowest, but there's no inherent meaning in sorting surface types with *similar* weights
|
||||
// together.
|
||||
|
||||
if (tagWeight1.m_weight != tagWeight2.m_weight)
|
||||
{
|
||||
return tagWeight1.m_weight > tagWeight2.m_weight;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using SurfaceTagWeightList = AZStd::vector<SurfaceTagWeight>;
|
||||
|
||||
struct SurfacePoint final
|
||||
{
|
||||
AZ_TYPE_INFO(SurfacePoint, "{331A3D0E-BB1D-47BF-96A2-249FAA0D720D}");
|
||||
|
||||
AZ::Vector3 m_position;
|
||||
AZ::Vector3 m_normal;
|
||||
SurfaceTagWeightList m_surfaceTags;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
} // namespace AzFramework::SurfaceData
|
||||
@@ -8,56 +8,33 @@
|
||||
|
||||
#include "TerrainDataRequestBus.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
namespace AzFramework::Terrain
|
||||
{
|
||||
namespace SurfaceData
|
||||
void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context)
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<SurfaceTagWeight>()
|
||||
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType)
|
||||
->Field("m_weight", &SurfaceTagWeight::m_weight)
|
||||
;
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<SurfaceTagWeight>("SurfaceTagWeight")
|
||||
->Property("m_surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType))
|
||||
->Property("m_weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight))
|
||||
;
|
||||
}
|
||||
}
|
||||
} //namespace SurfaceData
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Terrain")
|
||||
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
|
||||
->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightFromFloats)
|
||||
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
|
||||
->Event("GetMaxSurfaceWeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromFloats)
|
||||
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
|
||||
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
|
||||
->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats)
|
||||
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
|
||||
->Event("GetTerrainHeightQueryResolution",
|
||||
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, "Terrain")
|
||||
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
|
||||
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
|
||||
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
|
||||
->Event("GetMaxSurfaceWeightFromVector2",
|
||||
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromVector2)
|
||||
->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeights)
|
||||
->Event("GetSurfaceWeightsFromVector2",
|
||||
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeightsFromVector2)
|
||||
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
|
||||
->Event("GetSurfacePoint", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePoint)
|
||||
->Event("GetSurfacePointFromVector2",
|
||||
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePointFromVector2)
|
||||
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
|
||||
->Event("GetTerrainHeightQueryResolution",
|
||||
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
|
||||
;
|
||||
}
|
||||
|
||||
} //namespace Terrain
|
||||
} // namespace AzFramework
|
||||
}
|
||||
} // namespace AzFramework::Terrain
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user