merging dev
Signed-off-by: antonmic <56370189+antonmic@users.noreply.github.com>
This commit is contained in:
@@ -54,6 +54,30 @@ def get_mesh_node_names(sceneGraph):
|
||||
|
||||
return meshDataList, paths
|
||||
|
||||
def add_material_component(entity_id):
|
||||
# Create an override AZ::Render::EditorMaterialComponent
|
||||
editor_material_component = azlmbr.entity.EntityUtilityBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
"GetOrAddComponentByTypeName",
|
||||
entity_id,
|
||||
"EditorMaterialComponent")
|
||||
|
||||
# this fills out the material asset to a known product AZMaterial asset relative path
|
||||
json_update = json.dumps({
|
||||
"Controller": { "Configuration": { "materials": [
|
||||
{
|
||||
"Key": {},
|
||||
"Value": { "MaterialAsset":{
|
||||
"assetHint": "materials/basic_grey.azmaterial"
|
||||
}}
|
||||
}]
|
||||
}}
|
||||
});
|
||||
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, editor_material_component, json_update)
|
||||
|
||||
if not result:
|
||||
raise RuntimeError("UpdateComponentForEntity for editor_material_component failed")
|
||||
|
||||
def update_manifest(scene):
|
||||
import json
|
||||
import uuid, os
|
||||
@@ -74,6 +98,8 @@ def update_manifest(scene):
|
||||
source_filename_only = os.path.basename(clean_filename)
|
||||
|
||||
created_entities = []
|
||||
previous_entity_id = azlmbr.entity.InvalidEntityId
|
||||
first_mesh = True
|
||||
|
||||
# Loop every mesh node in the scene
|
||||
for activeMeshIndex in range(len(mesh_name_list)):
|
||||
@@ -102,14 +128,38 @@ def update_manifest(scene):
|
||||
# The MeshGroup we created will be output as a product in the asset's path named mesh_group_name.azmodel
|
||||
# The assetHint will be converted to an AssetId later during prefab loading
|
||||
json_update = json.dumps({
|
||||
"Controller": { "Configuration": { "ModelAsset": {
|
||||
"assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
|
||||
});
|
||||
"Controller": { "Configuration": { "ModelAsset": {
|
||||
"assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
|
||||
});
|
||||
# Apply the JSON above to the component we created
|
||||
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, editor_mesh_component, json_update)
|
||||
|
||||
if not result:
|
||||
raise RuntimeError("UpdateComponentForEntity failed")
|
||||
raise RuntimeError("UpdateComponentForEntity failed for Mesh component")
|
||||
|
||||
# an example of adding a material component to override the default material
|
||||
if previous_entity_id is not None and first_mesh:
|
||||
first_mesh = False
|
||||
add_material_component(entity_id)
|
||||
|
||||
# Get the transform component
|
||||
transform_component = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "GetOrAddComponentByTypeName", entity_id, "27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0")
|
||||
|
||||
# Set this entity to be a child of the last entity we created
|
||||
# This is just an example of how to do parenting and isn't necessarily useful to parent everything like this
|
||||
if previous_entity_id is not None:
|
||||
transform_json = json.dumps({
|
||||
"Parent Entity" : previous_entity_id.to_json()
|
||||
});
|
||||
|
||||
# Apply the JSON update
|
||||
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, transform_component, transform_json)
|
||||
|
||||
if not result:
|
||||
raise RuntimeError("UpdateComponentForEntity failed for Transform component")
|
||||
|
||||
# Update the last entity id for next time
|
||||
previous_entity_id = entity_id
|
||||
|
||||
# Keep track of the entity we set up, we'll add them all to the prefab we're creating later
|
||||
created_entities.append(entity_id)
|
||||
@@ -147,6 +197,8 @@ def on_update_manifest(args):
|
||||
except RuntimeError as err:
|
||||
print (f'ERROR - {err}')
|
||||
log_exception_traceback()
|
||||
except:
|
||||
log_exception_traceback()
|
||||
|
||||
global sceneJobHandler
|
||||
sceneJobHandler = None
|
||||
|
||||
@@ -54,4 +54,5 @@ set(ENABLED_GEMS
|
||||
AWSMetrics
|
||||
PrefabBuilder
|
||||
AudioSystem
|
||||
Profiler
|
||||
)
|
||||
|
||||
+2
-3
@@ -204,7 +204,7 @@ namespace PythonCoverage
|
||||
return coveringModuleOutputNames;
|
||||
}
|
||||
|
||||
void PythonCoverageEditorSystemComponent::OnStartExecuteByFilenameAsTest(AZStd::string_view filename, AZStd::string_view testCase, [[maybe_unused]] const AZStd::vector<AZStd::string_view>& args)
|
||||
void PythonCoverageEditorSystemComponent::OnStartExecuteByFilenameAsTest([[maybe_unused]]AZStd::string_view filename, AZStd::string_view testCase, [[maybe_unused]] const AZStd::vector<AZStd::string_view>& args)
|
||||
{
|
||||
if (m_coverageState == CoverageState::Disabled)
|
||||
{
|
||||
@@ -226,8 +226,7 @@ namespace PythonCoverage
|
||||
return;
|
||||
}
|
||||
|
||||
const AZStd::string scriptName = AZ::IO::Path(filename).Stem().Native();
|
||||
const auto coverageFile = m_coverageDir / AZStd::string::format("%s.pycoverage", scriptName.c_str());
|
||||
const auto coverageFile = m_coverageDir / AZStd::string::format("%.*s.pycoverage", AZ_STRING_ARG(testCase));
|
||||
|
||||
// If this is a different python script we clear the existing entity components and start afresh
|
||||
if (m_coverageFile != coverageFile)
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -71,5 +71,9 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_PostFXShapeWeightModifierAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C36525664")
|
||||
class AtomEditorComponents_PostFXGradientWeightModifierAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_PostFXGradientWeightModifierAdded as test_module
|
||||
|
||||
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
|
||||
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
class Tests:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
postfx_gradient_weight_creation = (
|
||||
"PostFX Gradient Weight Modifier Entity successfully created",
|
||||
"PostFX Gradient Weight Modifier Entity failed to be created")
|
||||
postfx_gradient_weight_component = (
|
||||
"Entity has a PostFX Gradient Weight Modifier component",
|
||||
"Entity failed to find PostFX Gradient Weight Modifier component")
|
||||
postfx_gradient_weight_disabled = (
|
||||
"PostFX Gradient Weight Modifier component disabled",
|
||||
"PostFX Gradient Weight Modifier component was not disabled.")
|
||||
postfx_layer_component = (
|
||||
"Entity has a PostFX Layer component",
|
||||
"Entity did not have an PostFX Layer component")
|
||||
postfx_gradient_weight_enabled = (
|
||||
"PostFX Gradient Weight Modifier component enabled",
|
||||
"PostFX Gradient Weight Modifier component was not enabled.")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_PostFXGradientWeightModifier_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the PostFX Gradient Weight Modifier component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create a PostFX Gradient Weight Modifier entity with no components.
|
||||
2) Add a PostFX Gradient Weight Modifier component to PostFX Gradient Weight Modifier entity.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Verify PostFX Gradient Weight Modifier component not enabled.
|
||||
6) Add PostFX Layer component since it is required by the PostFX Gradient Weight Modifier component.
|
||||
7) Verify PostFX Gradient Weight Modifier component is enabled.
|
||||
8) Enter/Exit game mode.
|
||||
9) Test IsHidden.
|
||||
10) Test IsVisible.
|
||||
11) Delete PostFX Gradient Weight Modifier entity.
|
||||
12) UNDO deletion.
|
||||
13) REDO deletion.
|
||||
14) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create a PostFX Gradient Weight Modifier entity with no components.
|
||||
postfx_gradient_weight_name = "PostFX Gradient Weight Modifier"
|
||||
postfx_gradient_weight_entity = EditorEntity.create_editor_entity(postfx_gradient_weight_name)
|
||||
Report.critical_result(Tests.postfx_gradient_weight_creation, postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 2. Add a PostFX Gradient Weight Modifier component to PostFX Gradient Weight Modifier entity.
|
||||
postfx_gradient_weight_component = postfx_gradient_weight_entity.add_component(postfx_gradient_weight_name)
|
||||
Report.critical_result(
|
||||
Tests.postfx_gradient_weight_component,
|
||||
postfx_gradient_weight_entity.has_component(postfx_gradient_weight_name))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 5. Verify PostFX Gradient Weight Modifier component not enabled.
|
||||
Report.result(Tests.postfx_gradient_weight_disabled, not postfx_gradient_weight_component.is_enabled())
|
||||
|
||||
# 6. Add PostFX Layer component since it is required by the PostFX Gradient Weight Modifier component.
|
||||
postfx_layer_name = "PostFX Layer"
|
||||
postfx_gradient_weight_entity.add_component(postfx_layer_name)
|
||||
Report.result(Tests.postfx_layer_component, postfx_gradient_weight_entity.has_component(postfx_layer_name))
|
||||
|
||||
# 7. Verify PostFX Gradient Weight Modifier component is enabled.
|
||||
Report.result(Tests.postfx_gradient_weight_enabled, postfx_gradient_weight_component.is_enabled())
|
||||
|
||||
# 8. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 9. Test IsHidden.
|
||||
postfx_gradient_weight_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, postfx_gradient_weight_entity.is_hidden() is True)
|
||||
|
||||
# 10. Test IsVisible.
|
||||
postfx_gradient_weight_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, postfx_gradient_weight_entity.is_visible() is True)
|
||||
|
||||
# 11. Delete PostFX Gradient Weight Modifier entity.
|
||||
postfx_gradient_weight_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 12. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 13. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not postfx_gradient_weight_entity.exists())
|
||||
|
||||
# 14. Look for errors or asserts.
|
||||
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:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_PostFXGradientWeightModifier_AddedToEntity)
|
||||
-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.
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ def launch_and_validate_results(request, test_directory, editor, editor_script,
|
||||
logger.debug("Running automated test: {}".format(editor_script))
|
||||
editor.args.extend(["--skipWelcomeScreenDialog", "--regset=/Amazon/Settings/EnableSourceControl=false",
|
||||
"--regset=/Amazon/Preferences/EnablePrefabSystem=false", run_python, test_case,
|
||||
f"--pythontestcase={request.node.originalname}", "--runpythonargs", " ".join(cfg_args)])
|
||||
f"--pythontestcase={request.node.name}", "--runpythonargs", " ".join(cfg_args)])
|
||||
if auto_test_mode:
|
||||
editor.args.extend(["--autotest_mode"])
|
||||
if null_renderer:
|
||||
|
||||
+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 = []
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ def ForceRegion_LinearDampingForceOnRigidBodies():
|
||||
|
||||
# Constants
|
||||
CLOSE_ENOUGH = 0.001
|
||||
TIME_OUT = 3.0
|
||||
TIME_OUT = 10.0
|
||||
INITIAL_VELOCITY = azmath.Vector3(0.0, 0.0, -10.0)
|
||||
|
||||
# 1) Open level / Enter game mode
|
||||
|
||||
+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):
|
||||
"""
|
||||
|
||||
@@ -90,7 +90,7 @@ class TestAutomationBase:
|
||||
editor_starttime = time.time()
|
||||
self.logger.debug("Running automated test")
|
||||
testcase_module_filepath = self._get_testcase_module_filepath(testcase_module)
|
||||
pycmd = ["--runpythontest", testcase_module_filepath, f"-pythontestcase={request.node.originalname}"]
|
||||
pycmd = ["--runpythontest", testcase_module_filepath, f"-pythontestcase={request.node.name}"]
|
||||
if use_null_renderer:
|
||||
pycmd += ["-rhi=null"]
|
||||
if batch_mode:
|
||||
|
||||
@@ -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,44 +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
|
||||
|
||||
|
||||
UI Apps: AutomatedTesting.GameLauncher
|
||||
Launch AutomatedTesting.GameLauncher with Simple level
|
||||
Test should run in both gpu and non gpu
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import psutil
|
||||
|
||||
import ly_test_tools.environment.waiter as waiter
|
||||
import editor_python_test_tools.hydra_test_utils as editor_test_utils
|
||||
from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
|
||||
from ly_remote_console.remote_console_commands import (
|
||||
send_command_and_expect_response as send_command_and_expect_response,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("launcher_platform", ["windows"])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("level", ["Simple"])
|
||||
@pytest.mark.SUITE_smoke
|
||||
class TestRemoteConsoleLoadLevelWorks(object):
|
||||
@pytest.fixture
|
||||
def remote_console_instance(self, request):
|
||||
console = RemoteConsole()
|
||||
|
||||
def teardown():
|
||||
if console.connected:
|
||||
console.stop()
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return console
|
||||
|
||||
def test_RemoteConsole_LoadLevel_Works(self, launcher, level, remote_console_instance, launcher_platform):
|
||||
expected_lines = ['Level system is loading "Simple"']
|
||||
|
||||
editor_test_utils.launch_and_validate_results_launcher(launcher, level, remote_console_instance, expected_lines, null_renderer=True)
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e4937547ca4c486ef59656314401933217e0e0401fec103e1fb91c25ec60a177
|
||||
size 2806
|
||||
oid sha256:a5f9e27e0f22c31ca61d866fb594c6fde5b8ceb891e17dda075fa1e0033ec2b9
|
||||
size 1666
|
||||
|
||||
@@ -17,13 +17,6 @@
|
||||
"Gems/PhysicsEntities"
|
||||
]
|
||||
},
|
||||
"PhysXSamples":
|
||||
{
|
||||
"SourcePaths":
|
||||
[
|
||||
"Gems/PhysXSamples"
|
||||
]
|
||||
},
|
||||
"PrimitiveAssets":
|
||||
{
|
||||
"SourcePaths":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,10 +19,16 @@ namespace Editor
|
||||
if (GetIEditor()->IsInGameMode())
|
||||
{
|
||||
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
|
||||
// We need to handle RAW Input events in a separate loop. This is a workaround to enable XInput2 RAW Inputs using Editor mode.
|
||||
// TODO To have this call here might be not be perfect.
|
||||
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::PollSpecialEvents);
|
||||
|
||||
// Now handle the rest of the events.
|
||||
AzFramework::XcbEventHandlerBus::Broadcast(
|
||||
&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace Editor
|
||||
|
||||
+18
-16
@@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -513,7 +514,7 @@ public:
|
||||
QString m_appRoot;
|
||||
QString m_logFile;
|
||||
QString m_pythonArgs;
|
||||
QString m_pythontTestCase;
|
||||
QString m_pythonTestCase;
|
||||
QString m_execFile;
|
||||
QString m_execLineCmd;
|
||||
|
||||
@@ -562,7 +563,7 @@ public:
|
||||
const std::vector<std::pair<CommandLineStringOption, QString&> > stringOptions = {
|
||||
{{"logfile", "File name of the log file to write out to.", "logfile"}, m_logFile},
|
||||
{{"runpythonargs", "Command-line argument string to pass to the python script if --runpython or --runpythontest was used.", "runpythonargs"}, m_pythonArgs},
|
||||
{{"pythontestcase", "Test case name of python test script if --runpythontest was used.", "pythontestcase"}, m_pythontTestCase},
|
||||
{{"pythontestcase", "Test case name of python test script if --runpythontest was used.", "pythontestcase"}, m_pythonTestCase},
|
||||
{{"exec", "cfg file to run on startup, used for systems like automation", "exec"}, m_execFile},
|
||||
{{"rhi", "Command-line argument to force which rhi to use", "dummyString"}, dummyString },
|
||||
{{"rhi-device-validation", "Command-line argument to configure rhi validation", "dummyString"}, dummyString },
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1535,11 +1536,12 @@ void CCryEditApp::RunInitPythonScript(CEditCommandLineInfo& cmdInfo)
|
||||
{
|
||||
// Multiple testcases can be specified them with ';', these should match the files to run
|
||||
AZStd::vector<AZStd::string_view> testcaseList;
|
||||
QByteArray pythonTestCase = cmdInfo.m_pythonTestCase.toUtf8();
|
||||
testcaseList.resize(fileList.size());
|
||||
{
|
||||
int i = 0;
|
||||
AzFramework::StringFunc::TokenizeVisitor(
|
||||
fileStr.constData(),
|
||||
pythonTestCase.constData(),
|
||||
[&i, &testcaseList](AZStd::string_view elem)
|
||||
{
|
||||
testcaseList[i++] = (elem);
|
||||
@@ -2630,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());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -3364,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)
|
||||
{
|
||||
@@ -3404,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())
|
||||
{
|
||||
|
||||
+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)
|
||||
{
|
||||
|
||||
@@ -264,6 +264,9 @@ void EditorPreferencesDialog::SetFilter(const QString& filter)
|
||||
else if (m_currentPageItem)
|
||||
{
|
||||
m_currentPageItem->UpdateEditorFilter(ui->propertyEditor, m_filter);
|
||||
|
||||
// Refresh the Stylesheet - when using search functionality.
|
||||
AzQtComponents::StyleManager::repolishStyleSheet(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
#include "EditorViewportSettings.h"
|
||||
|
||||
|
||||
|
||||
@@ -43,17 +44,16 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize)
|
||||
->Field("MaxCount", &AutoBackup::m_maxCount)
|
||||
->Field("RemindTime", &AutoBackup::m_remindTime);
|
||||
|
||||
serialize.Class<AssetBrowserSearch>()
|
||||
serialize.Class<AssetBrowserSettings>()
|
||||
->Version(1)
|
||||
->Field("Max number of items displayed", &AssetBrowserSearch::m_maxNumberOfItemsShownInSearch);
|
||||
->Field("MaxEntriesShownCount", &AssetBrowserSettings::m_maxNumberOfItemsShownInSearch);
|
||||
|
||||
serialize.Class<CEditorPreferencesPage_Files>()
|
||||
->Version(1)
|
||||
->Field("Files", &CEditorPreferencesPage_Files::m_files)
|
||||
->Field("Editors", &CEditorPreferencesPage_Files::m_editors)
|
||||
->Field("AutoBackup", &CEditorPreferencesPage_Files::m_autoBackup)
|
||||
->Field("AssetBrowserSearch", &CEditorPreferencesPage_Files::m_assetBrowserSearch);
|
||||
|
||||
->Field("AssetBrowserSettings", &CEditorPreferencesPage_Files::m_assetBrowserSettings);
|
||||
|
||||
AZ::EditContext* editContext = serialize.GetEditContext();
|
||||
if (editContext)
|
||||
@@ -85,9 +85,10 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 100)
|
||||
->DataElement(AZ::Edit::UIHandlers::SpinBox, &AutoBackup::m_remindTime, "Remind Time", "Auto Remind Every (Minutes)");
|
||||
|
||||
editContext->Class<AssetBrowserSearch>("Asset Browser Search View", "Asset Browser Search View")
|
||||
->DataElement(AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSearch::m_maxNumberOfItemsShownInSearch, "Maximum number of displayed items",
|
||||
"Maximum number of displayed items displayed in the Search View")
|
||||
editContext->Class<AssetBrowserSettings>("Asset Browser Settings", "Asset Browser Settings")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::SpinBox, &AssetBrowserSettings::m_maxNumberOfItemsShownInSearch, "Maximum number of displayed items",
|
||||
"Maximum number of items to display in the Search View.")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 50)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 5000);
|
||||
|
||||
@@ -97,7 +98,7 @@ void CEditorPreferencesPage_Files::Reflect(AZ::SerializeContext& serialize)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_files, "Files", "File Preferences")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_editors, "External Editors", "External Editors")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_autoBackup, "Auto Backup", "Auto Backup")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_assetBrowserSearch, "Asset Browser Search", "Asset Browser Search");
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_Files::m_assetBrowserSettings, "Asset Browser Settings","Asset Browser Settings");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +118,7 @@ QIcon& CEditorPreferencesPage_Files::GetIcon()
|
||||
void CEditorPreferencesPage_Files::OnApply()
|
||||
{
|
||||
using namespace AzToolsFramework::SliceUtilities;
|
||||
|
||||
auto sliceSettings = AZ::UserSettings::CreateFind<SliceUserSettings>(AZ_CRC("SliceUserSettings", 0x055b32eb), AZ::UserSettings::CT_LOCAL);
|
||||
sliceSettings->m_autoNumber = m_files.m_autoNumberSlices;
|
||||
sliceSettings->m_saveLocation = m_files.m_saveLocation;
|
||||
@@ -137,7 +139,7 @@ void CEditorPreferencesPage_Files::OnApply()
|
||||
gSettings.autoBackupMaxCount = m_autoBackup.m_maxCount;
|
||||
gSettings.autoRemindTime = m_autoBackup.m_remindTime;
|
||||
|
||||
gSettings.maxNumberOfItemsShownInSearch = m_assetBrowserSearch.m_maxNumberOfItemsShownInSearch;
|
||||
SandboxEditor::SetMaxItemsShownInAssetBrowserSearch(m_assetBrowserSettings.m_maxNumberOfItemsShownInSearch);
|
||||
}
|
||||
|
||||
void CEditorPreferencesPage_Files::InitializeSettings()
|
||||
@@ -163,5 +165,5 @@ void CEditorPreferencesPage_Files::InitializeSettings()
|
||||
m_autoBackup.m_maxCount = gSettings.autoBackupMaxCount;
|
||||
m_autoBackup.m_remindTime = gSettings.autoRemindTime;
|
||||
|
||||
m_assetBrowserSearch.m_maxNumberOfItemsShownInSearch = gSettings.maxNumberOfItemsShownInSearch;
|
||||
m_assetBrowserSettings.m_maxNumberOfItemsShownInSearch = SandboxEditor::MaxItemsShownInAssetBrowserSearch();
|
||||
}
|
||||
|
||||
@@ -69,18 +69,15 @@ private:
|
||||
int m_remindTime;
|
||||
};
|
||||
|
||||
struct AssetBrowserSearch
|
||||
struct AssetBrowserSettings
|
||||
{
|
||||
AZ_TYPE_INFO(AssetBrowserSearch, "{9FBFCD24-9452-49DF-99F4-2711443CEAAE}")
|
||||
|
||||
int m_maxNumberOfItemsShownInSearch;
|
||||
AZ_TYPE_INFO(AssetBrowserSettings, "{5F407EC4-BBD1-4A87-92DB-D938D7127BB0}")
|
||||
AZ::u64 m_maxNumberOfItemsShownInSearch;
|
||||
};
|
||||
|
||||
Files m_files;
|
||||
ExternalEditors m_editors;
|
||||
AutoBackup m_autoBackup;
|
||||
AssetBrowserSearch m_assetBrowserSearch;
|
||||
AssetBrowserSettings m_assetBrowserSettings;
|
||||
QIcon m_icon;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,10 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
->Field("CaptureCursorLook", &CameraMovementSettings::m_captureCursorLook)
|
||||
->Field("OrbitYawRotationInverted", &CameraMovementSettings::m_orbitYawRotationInverted)
|
||||
->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX)
|
||||
->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY);
|
||||
->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY)
|
||||
->Field("DefaultPositionX", &CameraMovementSettings::m_defaultCameraPositionX)
|
||||
->Field("DefaultPositionY", &CameraMovementSettings::m_defaultCameraPositionY)
|
||||
->Field("DefaultPositionZ", &CameraMovementSettings::m_defaultCameraPositionZ);
|
||||
|
||||
serialize.Class<CameraInputSettings>()
|
||||
->Version(2)
|
||||
@@ -154,7 +157,16 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
"Invert direction of pan in local Y axis")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_captureCursorLook, "Camera Capture Look Cursor",
|
||||
"Should the cursor be captured (hidden) while performing free look");
|
||||
"Should the cursor be captured (hidden) while performing free look")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionX, "Default X Camera Position",
|
||||
"Default X Camera Position when a level is opened")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionY, "Default Y Camera Position",
|
||||
"Default Y Camera Position when a level is opened")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::SpinBox, &CameraMovementSettings::m_defaultCameraPositionZ, "Default Z Camera Position",
|
||||
"Default Z Camera Position when a level is opened");
|
||||
|
||||
editContext->Class<CameraInputSettings>("Camera Input Settings", "")
|
||||
->DataElement(
|
||||
@@ -271,6 +283,12 @@ void CEditorPreferencesPage_ViewportCamera::OnApply()
|
||||
SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted);
|
||||
SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX);
|
||||
SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY);
|
||||
SandboxEditor::SetDefaultCameraEditorPosition(
|
||||
AZ::Vector3(
|
||||
m_cameraMovementSettings.m_defaultCameraPositionX,
|
||||
m_cameraMovementSettings.m_defaultCameraPositionY,
|
||||
m_cameraMovementSettings.m_defaultCameraPositionZ
|
||||
));
|
||||
|
||||
SandboxEditor::SetCameraTranslateForwardChannelId(m_cameraInputSettings.m_translateForwardChannelId);
|
||||
SandboxEditor::SetCameraTranslateBackwardChannelId(m_cameraInputSettings.m_translateBackwardChannelId);
|
||||
@@ -308,6 +326,11 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings()
|
||||
m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX();
|
||||
m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY();
|
||||
|
||||
AZ::Vector3 defaultCameraPosition = SandboxEditor::DefaultEditorCameraPosition();
|
||||
m_cameraMovementSettings.m_defaultCameraPositionX = defaultCameraPosition.GetX();
|
||||
m_cameraMovementSettings.m_defaultCameraPositionY = defaultCameraPosition.GetY();
|
||||
m_cameraMovementSettings.m_defaultCameraPositionZ = defaultCameraPosition.GetZ();
|
||||
|
||||
m_cameraInputSettings.m_translateForwardChannelId = SandboxEditor::CameraTranslateForwardChannelId().GetName();
|
||||
m_cameraInputSettings.m_translateBackwardChannelId = SandboxEditor::CameraTranslateBackwardChannelId().GetName();
|
||||
m_cameraInputSettings.m_translateLeftChannelId = SandboxEditor::CameraTranslateLeftChannelId().GetName();
|
||||
|
||||
@@ -57,6 +57,9 @@ private:
|
||||
bool m_orbitYawRotationInverted;
|
||||
bool m_panInvertedX;
|
||||
bool m_panInvertedY;
|
||||
float m_defaultCameraPositionX;
|
||||
float m_defaultCameraPositionY;
|
||||
float m_defaultCameraPositionZ;
|
||||
|
||||
AZ::Crc32 RotateSmoothingVisibility() const
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
namespace SandboxEditor
|
||||
{
|
||||
constexpr AZStd::string_view AssetBrowserMaxItemsShownInSearchSetting = "/Amazon/Preferences/Editor/AssetBrowser/MaxItemsShowInSearch";
|
||||
constexpr AZStd::string_view GridSnappingSetting = "/Amazon/Preferences/Editor/GridSnapping";
|
||||
constexpr AZStd::string_view GridSizeSetting = "/Amazon/Preferences/Editor/GridSize";
|
||||
constexpr AZStd::string_view AngleSnappingSetting = "/Amazon/Preferences/Editor/AngleSnapping";
|
||||
@@ -51,6 +52,9 @@ namespace SandboxEditor
|
||||
constexpr AZStd::string_view CameraOrbitDollyIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitDollyId";
|
||||
constexpr AZStd::string_view CameraOrbitPanIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitPanId";
|
||||
constexpr AZStd::string_view CameraFocusIdSetting = "/Amazon/Preferences/Editor/Camera/FocusId";
|
||||
constexpr AZStd::string_view CameraDefaultStartingPositionX = "/Amazon/Preferences/Editor/Camera/DefaultStartingPosition/x";
|
||||
constexpr AZStd::string_view CameraDefaultStartingPositionY = "/Amazon/Preferences/Editor/Camera/DefaultStartingPosition/y";
|
||||
constexpr AZStd::string_view CameraDefaultStartingPositionZ = "/Amazon/Preferences/Editor/Camera/DefaultStartingPosition/z";
|
||||
|
||||
template<typename T>
|
||||
void SetRegistry(const AZStd::string_view setting, T&& value)
|
||||
@@ -110,6 +114,31 @@ namespace SandboxEditor
|
||||
return AZStd::make_unique<EditorViewportSettingsCallbacksImpl>();
|
||||
}
|
||||
|
||||
AZ::Vector3 DefaultEditorCameraPosition()
|
||||
{
|
||||
float xPosition = aznumeric_cast<float>(GetRegistry(CameraDefaultStartingPositionX, 0.0));
|
||||
float yPosition = aznumeric_cast<float>(GetRegistry(CameraDefaultStartingPositionY, -10.0));
|
||||
float zPosition = aznumeric_cast<float>(GetRegistry(CameraDefaultStartingPositionZ, 4.0));
|
||||
return AZ::Vector3(xPosition, yPosition, zPosition);
|
||||
}
|
||||
|
||||
void SetDefaultCameraEditorPosition(const AZ::Vector3 defaultCameraPosition)
|
||||
{
|
||||
SetRegistry(CameraDefaultStartingPositionX, defaultCameraPosition.GetX());
|
||||
SetRegistry(CameraDefaultStartingPositionY, defaultCameraPosition.GetY());
|
||||
SetRegistry(CameraDefaultStartingPositionZ, defaultCameraPosition.GetZ());
|
||||
}
|
||||
|
||||
AZ::u64 MaxItemsShownInAssetBrowserSearch()
|
||||
{
|
||||
return GetRegistry(AssetBrowserMaxItemsShownInSearchSetting, aznumeric_cast<AZ::u64>(50));
|
||||
}
|
||||
|
||||
void SetMaxItemsShownInAssetBrowserSearch(const AZ::u64 numberOfItemsShown)
|
||||
{
|
||||
SetRegistry(AssetBrowserMaxItemsShownInSearchSetting, numberOfItemsShown);
|
||||
}
|
||||
|
||||
bool GridSnappingEnabled()
|
||||
{
|
||||
return GetRegistry(GridSnappingSetting, false);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzFramework/Input/Channels/InputChannelId.h>
|
||||
|
||||
namespace SandboxEditor
|
||||
@@ -32,6 +33,12 @@ namespace SandboxEditor
|
||||
//! event will fire when a value in the settings registry (editorpreferences.setreg) is modified.
|
||||
SANDBOX_API AZStd::unique_ptr<EditorViewportSettingsCallbacks> CreateEditorViewportSettingsCallbacks();
|
||||
|
||||
SANDBOX_API AZ::Vector3 DefaultEditorCameraPosition();
|
||||
SANDBOX_API void SetDefaultCameraEditorPosition(AZ::Vector3 defaultCameraPosition);
|
||||
|
||||
SANDBOX_API AZ::u64 MaxItemsShownInAssetBrowserSearch();
|
||||
SANDBOX_API void SetMaxItemsShownInAssetBrowserSearch(AZ::u64 numberOfItemsShown);
|
||||
|
||||
SANDBOX_API bool GridSnappingEnabled();
|
||||
SANDBOX_API void SetGridSnapping(bool enabled);
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ void StartFixedCursorMode(QObject *viewport);
|
||||
|
||||
#define RENDER_MESH_TEST_DISTANCE (0.2f)
|
||||
#define CURSOR_FONT_HEIGHT 8.0f
|
||||
|
||||
namespace AZ::ViewportHelpers
|
||||
{
|
||||
static const char TextCantCreateCameraNoLevel[] = "Cannot create camera when no level is loaded.";
|
||||
@@ -623,16 +622,10 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
PopDisableRendering();
|
||||
|
||||
{
|
||||
AZ::Aabb terrainAabb = AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainAabb, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb);
|
||||
float sx = terrainAabb.GetXExtent();
|
||||
float sy = terrainAabb.GetYExtent();
|
||||
|
||||
Matrix34 viewTM;
|
||||
viewTM.SetIdentity();
|
||||
// Initial camera will be at middle of the map at the height of 2
|
||||
// meters above the terrain (default terrain height is 32)
|
||||
viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f));
|
||||
|
||||
viewTM.SetTranslation(Vec3(m_editorViewportSettings.DefaultEditorCameraPosition()));
|
||||
SetViewTM(viewTM);
|
||||
|
||||
UpdateScene();
|
||||
@@ -647,16 +640,10 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
PopDisableRendering();
|
||||
|
||||
{
|
||||
AZ::Aabb terrainAabb = AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainAabb, &AzFramework::Terrain::TerrainDataRequests::GetTerrainAabb);
|
||||
float sx = terrainAabb.GetXExtent();
|
||||
float sy = terrainAabb.GetYExtent();
|
||||
|
||||
Matrix34 viewTM;
|
||||
viewTM.SetIdentity();
|
||||
// Initial camera will be at middle of the map at the height of 2
|
||||
// meters above the terrain (default terrain height is 32)
|
||||
viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f));
|
||||
|
||||
viewTM.SetTranslation(Vec3(m_editorViewportSettings.DefaultEditorCameraPosition()));
|
||||
SetViewTM(viewTM);
|
||||
}
|
||||
break;
|
||||
@@ -1345,10 +1332,6 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event)
|
||||
|
||||
void EditorViewportWidget::SetViewTM(const Matrix34& tm)
|
||||
{
|
||||
if (m_viewSourceType == ViewSourceType::None)
|
||||
{
|
||||
m_defaultViewTM = tm;
|
||||
}
|
||||
SetViewTM(tm, false);
|
||||
}
|
||||
|
||||
@@ -1445,6 +1428,10 @@ void EditorViewportWidget::SetViewTM(const Matrix34& camMatrix, bool bMoveOnly)
|
||||
"Please report this as a bug."
|
||||
);
|
||||
}
|
||||
else if (shouldUpdateObject == ShouldUpdateObject::No)
|
||||
{
|
||||
GetCurrentAtomView()->SetCameraTransform(LYTransformToAZMatrix3x4(camMatrix));
|
||||
}
|
||||
|
||||
if (m_pressedKeyState == KeyPressedState::PressedThisFrame)
|
||||
{
|
||||
@@ -2028,6 +2015,9 @@ void EditorViewportWidget::SetDefaultCamera()
|
||||
m_viewSourceType = ViewSourceType::None;
|
||||
GetViewManager()->SetCameraObjectId(GUID_NULL);
|
||||
SetName(m_defaultViewName);
|
||||
|
||||
// Set the default Editor Camera position.
|
||||
m_defaultViewTM.SetTranslation(Vec3(m_editorViewportSettings.DefaultEditorCameraPosition()));
|
||||
SetViewTM(m_defaultViewTM);
|
||||
|
||||
// Synchronize the configured editor viewport FOV to the default camera
|
||||
@@ -2530,6 +2520,11 @@ bool EditorViewportSettings::StickySelectEnabled() const
|
||||
return SandboxEditor::StickySelectEnabled();
|
||||
}
|
||||
|
||||
AZ::Vector3 EditorViewportSettings::DefaultEditorCameraPosition() const
|
||||
{
|
||||
return SandboxEditor::DefaultEditorCameraPosition();
|
||||
}
|
||||
|
||||
AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once);
|
||||
|
||||
bool EditorViewportWidget::ShouldPreviewFullscreen() const
|
||||
@@ -2641,5 +2636,4 @@ void EditorViewportWidget::StopFullscreenPreview()
|
||||
// Show the main window
|
||||
MainWindow::instance()->show();
|
||||
}
|
||||
|
||||
#include <moc_EditorViewportWidget.cpp>
|
||||
|
||||
@@ -78,6 +78,7 @@ struct EditorViewportSettings : public AzToolsFramework::ViewportInteraction::Vi
|
||||
float ManipulatorLineBoundWidth() const override;
|
||||
float ManipulatorCircleBoundWidth() const override;
|
||||
bool StickySelectEnabled() const override;
|
||||
AZ::Vector3 DefaultEditorCameraPosition() const override;
|
||||
};
|
||||
|
||||
// EditorViewportWidget window
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -108,15 +108,11 @@ CObjectManager::CObjectManager()
|
||||
|
||||
m_objectsByName.reserve(1024);
|
||||
LoadRegistry();
|
||||
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CObjectManager::~CObjectManager()
|
||||
{
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
|
||||
|
||||
m_bExiting = true;
|
||||
SaveRegistry();
|
||||
DeleteAllObjects();
|
||||
@@ -2307,37 +2303,6 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::OnEditorModeActivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
// hide current gizmo for entity (translate/rotate/scale)
|
||||
IGizmoManager* gizmoManager = GetGizmoManager();
|
||||
const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
|
||||
for (size_t i = 0; i < gizmoCount; ++i)
|
||||
{
|
||||
gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::OnEditorModeDeactivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
// show translate/rotate/scale gizmo again
|
||||
if (IGizmoManager* gizmoManager = GetGizmoManager())
|
||||
{
|
||||
if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
|
||||
{
|
||||
gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "ObjectManagerEventBus.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <Include/SandboxAPI.h>
|
||||
@@ -59,7 +58,6 @@ public:
|
||||
*/
|
||||
class CObjectManager
|
||||
: public IObjectManager
|
||||
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
|
||||
{
|
||||
public:
|
||||
//! Selection functor callback.
|
||||
@@ -330,12 +328,6 @@ private:
|
||||
|
||||
void FindDisplayableObjects(DisplayContext& dc, bool bDisplay);
|
||||
|
||||
// ViewportEditorModeNotificationsBus overrides ...
|
||||
void OnEditorModeActivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
void OnEditorModeDeactivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
|
||||
private:
|
||||
typedef std::map<GUID, CBaseObjectPtr, guid_less_predicate> Objects;
|
||||
Objects m_objects;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Settings.h"
|
||||
#include "EditorViewportSettings.h"
|
||||
|
||||
// Qt
|
||||
#include <QGuiApplication>
|
||||
@@ -487,7 +488,6 @@ void SEditorSettings::Save()
|
||||
SaveValue("Settings", "AutoBackupTime", autoBackupTime);
|
||||
SaveValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount);
|
||||
SaveValue("Settings", "AutoRemindTime", autoRemindTime);
|
||||
SaveValue("Settings", "MaxDisplayedItemsNumInSearch", maxNumberOfItemsShownInSearch);
|
||||
SaveValue("Settings", "CameraMoveSpeed", cameraMoveSpeed);
|
||||
SaveValue("Settings", "CameraRotateSpeed", cameraRotateSpeed);
|
||||
SaveValue("Settings", "StylusMode", stylusMode);
|
||||
@@ -682,7 +682,6 @@ void SEditorSettings::Load()
|
||||
LoadValue("Settings", "AutoBackupTime", autoBackupTime);
|
||||
LoadValue("Settings", "AutoBackupMaxCount", autoBackupMaxCount);
|
||||
LoadValue("Settings", "AutoRemindTime", autoRemindTime);
|
||||
LoadValue("Settings", "MaxDisplayedItemsNumInSearch", maxNumberOfItemsShownInSearch);
|
||||
LoadValue("Settings", "CameraMoveSpeed", cameraMoveSpeed);
|
||||
LoadValue("Settings", "CameraRotateSpeed", cameraRotateSpeed);
|
||||
LoadValue("Settings", "StylusMode", stylusMode);
|
||||
@@ -1174,7 +1173,7 @@ AzToolsFramework::ConsoleColorTheme SEditorSettings::GetConsoleColorTheme() cons
|
||||
return consoleBackgroundColorTheme;
|
||||
}
|
||||
|
||||
int SEditorSettings::GetMaxNumberOfItemsShownInSearchView() const
|
||||
AZ::u64 SEditorSettings::GetMaxNumberOfItemsShownInSearchView() const
|
||||
{
|
||||
return SEditorSettings::maxNumberOfItemsShownInSearch;
|
||||
return SandboxEditor::MaxItemsShownInAssetBrowserSearch();
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
SettingOutcome GetValue(const AZStd::string_view path) override;
|
||||
SettingOutcome SetValue(const AZStd::string_view path, const AZStd::any& value) override;
|
||||
AzToolsFramework::ConsoleColorTheme GetConsoleColorTheme() const override;
|
||||
int GetMaxNumberOfItemsShownInSearchView() const override;
|
||||
AZ::u64 GetMaxNumberOfItemsShownInSearchView() const override;
|
||||
|
||||
void ConvertPath(const AZStd::string_view sourcePath, AZStd::string& category, AZStd::string& attribute);
|
||||
|
||||
@@ -353,14 +353,6 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
int autoRemindTime;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Asset Browser Search View.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Current maximum number of items that can be displayed in the AssetBrowser Search View.
|
||||
int maxNumberOfItemsShownInSearch;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//! If true preview windows is displayed when browsing geometries.
|
||||
bool bPreviewGeometryWindow;
|
||||
|
||||
|
||||
@@ -1195,7 +1195,7 @@ bool CFileUtil::IsFileExclusivelyAccessable(const QString& strFilePath)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CFileUtil::CreatePath(const QString& strPath)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_MAC)
|
||||
#if !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
bool pathCreated = true;
|
||||
|
||||
QString cleanPath = QDir::cleanPath(strPath);
|
||||
@@ -1252,7 +1252,7 @@ bool CFileUtil::CreatePath(const QString& strPath)
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
#endif // !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -192,11 +192,86 @@ namespace AZ
|
||||
};
|
||||
|
||||
|
||||
//! SettingsRegistry notifier handler which is responsible for loading
|
||||
//! the project.json file at the new project path
|
||||
//! if an update to '<BootstrapSettingsRootKey>/project_path' key occurs.
|
||||
struct ProjectPathChangedEventHandler
|
||||
{
|
||||
ProjectPathChangedEventHandler(AZ::SettingsRegistryInterface& registry)
|
||||
: m_registry{ registry }
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
// Update the project settings when the project path is set
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
|
||||
|
||||
AZ::IO::FixedMaxPath newProjectPath;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path)
|
||||
&& m_registry.Get(newProjectPath.Native(), projectPathKey) && newProjectPath != m_oldProjectPath)
|
||||
{
|
||||
// Update old Project path before attempting to merge in new Settings Registry values in order to prevent recursive calls
|
||||
m_oldProjectPath = newProjectPath;
|
||||
|
||||
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
|
||||
AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath };
|
||||
projectMetadataFile /= "project.json";
|
||||
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
|
||||
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
|
||||
|
||||
// Update all the runtime file paths based on the new "project_path" value.
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::IO::FixedMaxPath m_oldProjectPath;
|
||||
AZ::SettingsRegistryInterface& m_registry;
|
||||
};
|
||||
|
||||
//! SettingsRegistry notifier handler which adds the project name as a specialization tag
|
||||
//! to the registry
|
||||
//! if an update to '<ProjectSettingsRootKey>/project_name' key occurs.
|
||||
struct ProjectNameChangedEventHandler
|
||||
{
|
||||
ProjectNameChangedEventHandler(AZ::SettingsRegistryInterface& registry)
|
||||
: m_registry{ registry }
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
// Update the project specialization when the project name is set
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name";
|
||||
|
||||
FixedValueString newProjectName;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path)
|
||||
&& m_registry.Get(newProjectName, projectNameKey) && newProjectName != m_oldProjectName)
|
||||
{
|
||||
// Add the project_name as a specialization for loading the build system dependency .setreg files
|
||||
auto newProjectNameSpecialization = FixedValueString::format("%s/%.*s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
|
||||
aznumeric_cast<int>(newProjectName.size()), newProjectName.data());
|
||||
auto oldProjectNameSpecialization = FixedValueString::format("%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
|
||||
m_oldProjectName.c_str());
|
||||
m_registry.Remove(oldProjectNameSpecialization);
|
||||
m_oldProjectName = newProjectName;
|
||||
m_registry.Set(newProjectNameSpecialization, true);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName;
|
||||
AZ::SettingsRegistryInterface& m_registry;
|
||||
};
|
||||
|
||||
//! SettingsRegistry notifier handler which updates relevant registry settings based
|
||||
//! on an update to '/Amazon/AzCore/Bootstrap/project_path' key.
|
||||
struct UpdateProjectSettingsEventHandler
|
||||
struct UpdateCommandLineEventHandler
|
||||
{
|
||||
UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
|
||||
UpdateCommandLineEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
|
||||
: m_registry{ registry }
|
||||
, m_commandLine{ commandLine }
|
||||
{
|
||||
@@ -204,70 +279,14 @@ namespace AZ
|
||||
|
||||
void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
// #1 Update the project settings when the project path is set
|
||||
const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
|
||||
AZ::IO::FixedMaxPath newProjectPath;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path)
|
||||
&& m_registry.Get(newProjectPath.Native(), projectPathKey) && newProjectPath != m_oldProjectPath)
|
||||
{
|
||||
UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath));
|
||||
}
|
||||
|
||||
// #2 Update the project specialization when the project name is set
|
||||
const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name";
|
||||
FixedValueString newProjectName;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path)
|
||||
&& m_registry.Get(newProjectName, projectNameKey) && newProjectName != m_oldProjectName)
|
||||
{
|
||||
UpdateProjectSpecializationFromProjectName(newProjectName);
|
||||
}
|
||||
|
||||
// #3 Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry
|
||||
// Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry
|
||||
if (path == AZ::SettingsRegistryMergeUtils::CommandLineValueChangedKey)
|
||||
{
|
||||
UpdateCommandLine();
|
||||
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine);
|
||||
}
|
||||
}
|
||||
|
||||
//! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path
|
||||
//! and remove the current project name specialization if one exists.
|
||||
void UpdateProjectSpecializationFromProjectName(AZStd::string_view newProjectName)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
// Add the project_name as a specialization for loading the build system dependency .setreg files
|
||||
auto newProjectNameSpecialization = FixedValueString::format("%s/%.*s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
|
||||
aznumeric_cast<int>(newProjectName.size()), newProjectName.data());
|
||||
auto oldProjectNameSpecialization = FixedValueString::format("%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
|
||||
m_oldProjectName.c_str());
|
||||
m_registry.Remove(oldProjectNameSpecialization);
|
||||
m_oldProjectName = newProjectName;
|
||||
m_registry.Set(newProjectNameSpecialization, true);
|
||||
}
|
||||
|
||||
void UpdateProjectSettingsFromProjectPath(AZ::IO::PathView newProjectPath)
|
||||
{
|
||||
// Update old Project path before attempting to merge in new Settings Registry values in order to prevent recursive calls
|
||||
m_oldProjectPath = newProjectPath;
|
||||
|
||||
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
|
||||
AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath };
|
||||
projectMetadataFile /= "project.json";
|
||||
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
|
||||
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
|
||||
|
||||
// Update all the runtime file paths based on the new "project_path" value.
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
|
||||
}
|
||||
|
||||
void UpdateCommandLine()
|
||||
{
|
||||
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine);
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::IO::FixedMaxPath m_oldProjectPath;
|
||||
AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName;
|
||||
AZ::SettingsRegistryInterface& m_registry;
|
||||
AZ::CommandLine& m_commandLine;
|
||||
};
|
||||
@@ -462,7 +481,12 @@ namespace AZ
|
||||
// 1. The 'project_path' key changes
|
||||
// 2. The project specialization when the 'project-name' key changes
|
||||
// 3. The ComponentApplication command line when the command line is stored to the registry
|
||||
m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry, m_commandLine });
|
||||
m_projectPathChangedHandler = m_settingsRegistry->RegisterNotifier(ProjectPathChangedEventHandler{
|
||||
*m_settingsRegistry });
|
||||
m_projectNameChangedHandler = m_settingsRegistry->RegisterNotifier(ProjectNameChangedEventHandler{
|
||||
*m_settingsRegistry });
|
||||
m_commandLineUpdatedHandler = m_settingsRegistry->RegisterNotifier(UpdateCommandLineEventHandler{
|
||||
*m_settingsRegistry, m_commandLine });
|
||||
|
||||
// Merge Command Line arguments
|
||||
constexpr bool executeRegDumpCommands = false;
|
||||
@@ -515,11 +539,12 @@ namespace AZ
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// The m_projectChangedHandler stores an AZStd::function internally
|
||||
// which allocates using the AZ SystemAllocator
|
||||
// m_projectChangedHandler is being default value initialized
|
||||
// to clear out the AZStd::function
|
||||
m_projectChangedHandler = {};
|
||||
// The SettingsRegistry Notify handlers stores an AZStd::function internally
|
||||
// which may allocates using the AZ SystemAllocator(if the functor > 16 bytes)
|
||||
// The handlers are being default value initialized to clear out the AZStd::function
|
||||
m_commandLineUpdatedHandler = {};
|
||||
m_projectNameChangedHandler = {};
|
||||
m_projectPathChangedHandler = {};
|
||||
|
||||
// Delete the AZ::IConsole if it was created by this application instance
|
||||
if (m_ownsConsole)
|
||||
|
||||
@@ -390,7 +390,9 @@ namespace AZ
|
||||
AZ::IO::FixedMaxPath m_engineRoot;
|
||||
AZ::IO::FixedMaxPath m_appRoot;
|
||||
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectChangedHandler;
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectPathChangedHandler;
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectNameChangedHandler;
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_commandLineUpdatedHandler;
|
||||
|
||||
// ConsoleFunctorHandle is responsible for unregistering the Settings Registry Console
|
||||
// from the m_console member when it goes out of scope
|
||||
|
||||
@@ -225,8 +225,16 @@ namespace AZ
|
||||
|
||||
ConsoleCommandContainer commandSubset;
|
||||
|
||||
for (ConsoleFunctorBase* curr = m_head; curr != nullptr; curr = curr->m_next)
|
||||
for (const auto& functor : m_commands)
|
||||
{
|
||||
if (functor.second.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter functors registered with the same name
|
||||
const ConsoleFunctorBase* curr = functor.second.front();
|
||||
|
||||
if ((curr->GetFlags() & ConsoleFunctorFlags::IsInvisible) == ConsoleFunctorFlags::IsInvisible)
|
||||
{
|
||||
// Filter functors marked as invisible
|
||||
@@ -236,7 +244,12 @@ namespace AZ
|
||||
if (StringFunc::StartsWith(curr->m_name, command, false))
|
||||
{
|
||||
AZLOG_INFO("- %s : %s\n", curr->m_name, curr->m_desc);
|
||||
commandSubset.push_back(curr->m_name);
|
||||
|
||||
if (commandSubset.size() < MaxConsoleCommandPlusArgsLength)
|
||||
{
|
||||
commandSubset.push_back(curr->m_name);
|
||||
}
|
||||
|
||||
if (matches)
|
||||
{
|
||||
matches->push_back(curr->m_name);
|
||||
@@ -271,7 +284,10 @@ namespace AZ
|
||||
{
|
||||
for (auto& curr : m_commands)
|
||||
{
|
||||
visitor(curr.second.front());
|
||||
if (!curr.second.empty())
|
||||
{
|
||||
visitor(curr.second.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +352,11 @@ namespace AZ
|
||||
{
|
||||
iter->second.erase(iter2);
|
||||
}
|
||||
|
||||
if (iter->second.empty())
|
||||
{
|
||||
m_commands.erase(iter);
|
||||
}
|
||||
}
|
||||
functor->Unlink(m_head);
|
||||
functor->m_console = nullptr;
|
||||
@@ -618,9 +639,10 @@ namespace AZ
|
||||
{
|
||||
// Make sure the there is a JSON object at the ConsoleRuntimeCommandKey or ConsoleAutoexecKey
|
||||
// So that JSON Patch is able to add values underneath that object (JSON Patch doesn't create intermediate objects)
|
||||
settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } } })"
|
||||
R"(,"O3DE": { "Autoexec": { "ConsoleCommands": {} } } })",
|
||||
SettingsRegistryInterface::Format::JsonMergePatch);
|
||||
settingsRegistry.MergeSettings(R"({})", SettingsRegistryInterface::Format::JsonMergePatch,
|
||||
IConsole::ConsoleRuntimeCommandKey);
|
||||
settingsRegistry.MergeSettings(R"({})", SettingsRegistryInterface::Format::JsonMergePatch,
|
||||
IConsole::ConsoleAutoexecCommandKey);
|
||||
m_consoleCommandKeyHandler = settingsRegistry.RegisterNotifier(ConsoleCommandKeyNotificationHandler{ settingsRegistry, *this });
|
||||
|
||||
JsonApplyPatchSettings applyPatchSettings;
|
||||
|
||||
@@ -40,6 +40,12 @@ namespace AZ
|
||||
static unsigned int Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned int suppressCount = 0, void* nativeThread = 0);
|
||||
};
|
||||
|
||||
class StackConverter
|
||||
{
|
||||
public:
|
||||
static unsigned int FromNative(StackFrame* frames, unsigned int maxNumOfFrames, void* nativeContext);
|
||||
};
|
||||
|
||||
class SymbolStorage
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace AZ
|
||||
{
|
||||
namespace Debug
|
||||
{
|
||||
struct StackFrame;
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
@@ -551,17 +553,19 @@ namespace AZ
|
||||
{
|
||||
StackFrame frames[25];
|
||||
|
||||
// Without StackFrame explicit alignment frames array is aligned to 4 bytes
|
||||
// which causes the stack tracing to fail.
|
||||
//size_t bla = AZStd::alignment_of<StackFrame>::value;
|
||||
//printf("Alignment value %d address 0x%08x : 0x%08x\n",bla,frames);
|
||||
SymbolStorage::StackLine lines[AZ_ARRAY_SIZE(frames)];
|
||||
unsigned int numFrames = 0;
|
||||
|
||||
if (!nativeContext)
|
||||
{
|
||||
suppressCount += 1; /// If we don't provide a context we will capture in the RecordFunction, so skip us (Trace::PrinCallstack).
|
||||
suppressCount += 1; /// If we don't provide a context we will capture in the RecordFunction, so skip us (Trace::PrintCallstack).
|
||||
numFrames = StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), suppressCount);
|
||||
}
|
||||
unsigned int numFrames = StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), suppressCount, nativeContext);
|
||||
else
|
||||
{
|
||||
numFrames = StackConverter::FromNative(frames, AZ_ARRAY_SIZE(frames), nativeContext);
|
||||
}
|
||||
|
||||
if (numFrames)
|
||||
{
|
||||
SymbolStorage::DecodeFrames(frames, numFrames, lines);
|
||||
@@ -573,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.
|
||||
|
||||
@@ -192,26 +192,34 @@ namespace AZ
|
||||
//! @param path An offset at which traversal should start.
|
||||
//! @return Whether or not entries could be visited.
|
||||
virtual bool Visit(const VisitorCallback& callback, AZStd::string_view path) const = 0;
|
||||
|
||||
//! Register a callback that will be called whenever an entry gets a new/updated value.
|
||||
//!
|
||||
//! @callback The function to call when an entry gets a new/updated value.
|
||||
[[nodiscard]] virtual NotifyEventHandler RegisterNotifier(const NotifyCallback& callback) = 0;
|
||||
//! Register a callback that will be called whenever an entry gets a new/updated value.
|
||||
//! @callback The function to call when an entry gets a new/updated value.
|
||||
[[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) = 0;
|
||||
//! @return NotifyEventHandler instance which must persist to receive event signal
|
||||
[[nodiscard]] virtual NotifyEventHandler RegisterNotifier(NotifyCallback callback) = 0;
|
||||
//! Register a notify event handler with the NotifyEvent.
|
||||
//! The handler will be called whenever an entry gets a new/updated value.
|
||||
//! @param handler The handler to register with the NotifyEvent.
|
||||
virtual void RegisterNotifier(NotifyEventHandler& handler) = 0;
|
||||
|
||||
//! Register a function that will be called before a file is merged.
|
||||
//! @callback The function to call before a file is merged.
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called before a file is merged.
|
||||
//! @callback The function to call before a file is merged.
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) = 0;
|
||||
//! @param callback The function to call before a file is merged.
|
||||
//! @return PreMergeEventHandler instance which must persist to receive event signal
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback callback) = 0;
|
||||
//! Register a pre-merge handler with the PreMergeEvent.
|
||||
//! The handler will be called before a file is merged.
|
||||
//! @param handler The hanlder to register with the PreMergeEvent.
|
||||
virtual void RegisterPreMergeEvent(PreMergeEventHandler& handler) = 0;
|
||||
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) = 0;
|
||||
//! @param callback The function to call after a file is merged.
|
||||
//! @return PostMergeEventHandler instance which must persist to receive event signal
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback callback) = 0;
|
||||
//! Register a post-merge hahndler with the PostMergeEvent.
|
||||
//! The handler will be called after a file is merged.
|
||||
//! @param handler The handler to register with the PostmergeEVent.
|
||||
virtual void RegisterPostMergeEvent(PostMergeEventHandler& hanlder) = 0;
|
||||
|
||||
//! Gets the boolean value at the provided path.
|
||||
//! @param result The target to write the result to.
|
||||
@@ -326,23 +334,25 @@ namespace AZ
|
||||
//! - all digits and dot -> floating point number
|
||||
//! - Everything else is considered a string.
|
||||
//! @param argument The command line argument.
|
||||
//! @param structure which contains functors which determine what characters are delimiters
|
||||
//! @param anchorKey The key where the merged command line argument will be anchored under
|
||||
//! @param commandLineSettings structure which contains functors which determine what characters are delimiters
|
||||
//! @return True if the command line argument could be parsed, otherwise false.
|
||||
virtual bool MergeCommandLineArgument(AZStd::string_view argument, AZStd::string_view rootKey = "",
|
||||
virtual bool MergeCommandLineArgument(AZStd::string_view argument, AZStd::string_view anchorKey = "",
|
||||
const CommandLineArgumentSettings& commandLineSettings = {}) = 0;
|
||||
//! Merges the json data provided into the settings registry.
|
||||
//! @param data The json data stored in a string.
|
||||
//! @param format The format of the provided data.
|
||||
//! @param anchorKey The key where the merged json content will be anchored under.
|
||||
//! @return True if the data was successfully merged, otherwise false.
|
||||
virtual bool MergeSettings(AZStd::string_view data, Format format) = 0;
|
||||
virtual bool MergeSettings(AZStd::string_view data, Format format, AZStd::string_view anchorKey = "") = 0;
|
||||
//! Loads a settings file and merges it into the registry.
|
||||
//! @param path The path to the registry file.
|
||||
//! @param format The format of the text data in the file at the provided path.
|
||||
//! @param rootKey The key where the root of the settings file will be stored under.
|
||||
//! @param anchorKey The key where the content of the settings file will be anchored.
|
||||
//! @param scratchBuffer An optional buffer that's used to load the file into. Use this when loading multiple patches to
|
||||
//! reduce the number of intermediate memory allocations.
|
||||
//! @return True if the registry file was successfully merged, otherwise false.
|
||||
virtual bool MergeSettingsFile(AZStd::string_view path, Format format, AZStd::string_view rootKey = "",
|
||||
virtual bool MergeSettingsFile(AZStd::string_view path, Format format, AZStd::string_view anchorKey = "",
|
||||
AZStd::vector<char>* scratchBuffer = nullptr) = 0;
|
||||
//! Loads all settings files in a folder and merges them into the registry.
|
||||
//! With the specializations "a" and "b" and platform "c" the files would be loaded in the order:
|
||||
@@ -357,11 +367,12 @@ namespace AZ
|
||||
//! @param platform An optional name of a platform. Platform overloads are located at <path>/Platform/<platform>/
|
||||
//! Files in a platform are applied in the same order as for the main folder but always after the same file
|
||||
//! in the main folder.
|
||||
//! @param anchorKey The registry path location where the settings will be anchored
|
||||
//! @param scratchBuffer An optional buffer that's used to load the file into. Use this when loading multiple patches to
|
||||
//! reduce the number of intermediate memory allocations.
|
||||
//! @return True if the registry folder was successfully merged, otherwise false.
|
||||
virtual bool MergeSettingsFolder(AZStd::string_view path, const Specializations& specializations,
|
||||
AZStd::string_view platform = {}, AZStd::string_view rootKey = "", AZStd::vector<char>* scratchBuffer = nullptr) = 0;
|
||||
AZStd::string_view platform = {}, AZStd::string_view anchorKey = "", AZStd::vector<char>* scratchBuffer = nullptr) = 0;
|
||||
|
||||
//! Stores the settings structure which is used when merging settings to the Settings Registry
|
||||
//! using JSON Merge Patch or JSON Merge Patch.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <AzCore/IO/FileReader.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/JSON/error/en.h>
|
||||
#include <AzCore/NativeUI//NativeUIRequests.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Serialization/Json/StackedString.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
@@ -21,6 +21,34 @@
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
|
||||
namespace AZ::SettingsRegistryImplInternal
|
||||
{
|
||||
AZ::SettingsRegistryInterface::Type RapidjsonToSettingsRegistryType(const rapidjson::Value& value)
|
||||
{
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
switch (value.GetType())
|
||||
{
|
||||
case rapidjson::Type::kNullType:
|
||||
return Type::Null;
|
||||
case rapidjson::Type::kFalseType:
|
||||
return Type::Boolean;
|
||||
case rapidjson::Type::kTrueType:
|
||||
return Type::Boolean;
|
||||
case rapidjson::Type::kObjectType:
|
||||
return Type::Object;
|
||||
case rapidjson::Type::kArrayType:
|
||||
return Type::Array;
|
||||
case rapidjson::Type::kStringType:
|
||||
return Type::String;
|
||||
case rapidjson::Type::kNumberType:
|
||||
return value.IsDouble() ? Type::FloatingPoint :
|
||||
Type::Integer;
|
||||
}
|
||||
|
||||
return Type::NoType;
|
||||
}
|
||||
}
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
template<typename T>
|
||||
@@ -28,7 +56,7 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
// rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
@@ -70,7 +98,7 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
// rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
@@ -161,7 +189,7 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
// rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
@@ -212,17 +240,7 @@ namespace AZ
|
||||
return Visit(visitor, path);
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterNotifier(const NotifyCallback& callback) -> NotifyEventHandler
|
||||
{
|
||||
NotifyEventHandler notifyHandler{ callback };
|
||||
{
|
||||
AZStd::scoped_lock lock(m_notifierMutex);
|
||||
notifyHandler.Connect(m_notifiers);
|
||||
}
|
||||
return notifyHandler;
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterNotifier(NotifyCallback&& callback) -> NotifyEventHandler
|
||||
auto SettingsRegistryImpl::RegisterNotifier(NotifyCallback callback) -> NotifyEventHandler
|
||||
{
|
||||
NotifyEventHandler notifyHandler{ AZStd::move(callback) };
|
||||
{
|
||||
@@ -232,23 +250,19 @@ namespace AZ
|
||||
return notifyHandler;
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterNotifier(NotifyEventHandler& notifyHandler) -> void
|
||||
{
|
||||
AZStd::scoped_lock lock(m_notifierMutex);
|
||||
notifyHandler.Connect(m_notifiers);
|
||||
}
|
||||
|
||||
void SettingsRegistryImpl::ClearNotifiers()
|
||||
{
|
||||
AZStd::scoped_lock lock(m_notifierMutex);
|
||||
m_notifiers.DisconnectAllHandlers();
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterPreMergeEvent(const PreMergeEventCallback& callback) -> PreMergeEventHandler
|
||||
{
|
||||
PreMergeEventHandler preMergeHandler{ callback };
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
preMergeHandler.Connect(m_preMergeEvent);
|
||||
}
|
||||
return preMergeHandler;
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventCallback&& callback) -> PreMergeEventHandler
|
||||
auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventCallback callback) -> PreMergeEventHandler
|
||||
{
|
||||
PreMergeEventHandler preMergeHandler{ AZStd::move(callback) };
|
||||
{
|
||||
@@ -258,17 +272,13 @@ namespace AZ
|
||||
return preMergeHandler;
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterPostMergeEvent(const PostMergeEventCallback& callback) -> PostMergeEventHandler
|
||||
auto SettingsRegistryImpl::RegisterPreMergeEvent(PreMergeEventHandler& preMergeHandler) -> void
|
||||
{
|
||||
PostMergeEventHandler postMergeHandler{ callback };
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
postMergeHandler.Connect(m_postMergeEvent);
|
||||
}
|
||||
return postMergeHandler;
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
preMergeHandler.Connect(m_preMergeEvent);
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventCallback&& callback) -> PostMergeEventHandler
|
||||
auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventCallback callback) -> PostMergeEventHandler
|
||||
{
|
||||
PostMergeEventHandler postMergeHandler{ AZStd::move(callback) };
|
||||
{
|
||||
@@ -278,6 +288,12 @@ namespace AZ
|
||||
return postMergeHandler;
|
||||
}
|
||||
|
||||
auto SettingsRegistryImpl::RegisterPostMergeEvent(PostMergeEventHandler& postMergeHandler) -> void
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
postMergeHandler.Connect(m_postMergeEvent);
|
||||
}
|
||||
|
||||
void SettingsRegistryImpl::ClearMergeEvents()
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
@@ -297,7 +313,36 @@ namespace AZ
|
||||
localNotifierEvent = AZStd::move(m_notifiers);
|
||||
}
|
||||
|
||||
localNotifierEvent.Signal(jsonPath, type);
|
||||
// Signal the NotifyEvent for each queued argument
|
||||
decltype(m_signalNotifierQueue) localNotifierQueue;
|
||||
{
|
||||
AZStd::scoped_lock signalLock(m_signalMutex);
|
||||
m_signalNotifierQueue.push_back({ FixedValueString{jsonPath}, type });
|
||||
// If the signal count was 0, then a dispatch is in progress
|
||||
if (m_signalCount++ == 0)
|
||||
{
|
||||
AZStd::swap(localNotifierQueue, m_signalNotifierQueue);
|
||||
}
|
||||
}
|
||||
|
||||
while (!localNotifierQueue.empty())
|
||||
{
|
||||
for (SignalNotifierArgs notifierArgs : localNotifierQueue)
|
||||
{
|
||||
localNotifierEvent.Signal(notifierArgs.m_jsonPath, notifierArgs.m_type);
|
||||
}
|
||||
// Clear the local notifier queue and check if more notifiers have been added
|
||||
localNotifierQueue = {};
|
||||
{
|
||||
AZStd::scoped_lock signalLock(m_signalMutex);
|
||||
AZStd::swap(localNotifierQueue, m_signalNotifierQueue);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AZStd::scoped_lock signalLock(m_signalMutex);
|
||||
--m_signalCount;
|
||||
}
|
||||
|
||||
{
|
||||
// Swap the local handlers with the current m_notifiers which
|
||||
@@ -314,39 +359,19 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
//rapidjson::Pointer assets that the supplied string
|
||||
//rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Pointer pointer(path.data(), path.length());
|
||||
if (pointer.IsValid())
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
const rapidjson::Value* value = pointer.Get(m_settings);
|
||||
if (value)
|
||||
if (const rapidjson::Value* value = pointer.Get(m_settings); value != nullptr)
|
||||
{
|
||||
switch (value->GetType())
|
||||
{
|
||||
case rapidjson::Type::kNullType:
|
||||
return Type::Null;
|
||||
case rapidjson::Type::kFalseType:
|
||||
return Type::Boolean;
|
||||
case rapidjson::Type::kTrueType:
|
||||
return Type::Boolean;
|
||||
case rapidjson::Type::kObjectType:
|
||||
return Type::Object;
|
||||
case rapidjson::Type::kArrayType:
|
||||
return Type::Array;
|
||||
case rapidjson::Type::kStringType:
|
||||
return Type::String;
|
||||
case rapidjson::Type::kNumberType:
|
||||
return
|
||||
value->IsDouble() ? Type::FloatingPoint :
|
||||
Type::Integer;
|
||||
}
|
||||
return SettingsRegistryImplInternal::RapidjsonToSettingsRegistryType(*value);
|
||||
}
|
||||
}
|
||||
return Type::NoType;
|
||||
@@ -392,7 +417,7 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
// rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
@@ -471,13 +496,12 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
//rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Pointer pointer(path.data(), path.length());
|
||||
if (pointer.IsValid())
|
||||
{
|
||||
@@ -486,10 +510,14 @@ namespace AZ
|
||||
value, nullptr, valueTypeID, m_serializationSettings);
|
||||
if (jsonResult.GetProcessing() != JsonSerializationResult::Processing::Halted)
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
rapidjson::Value& setting = pointer.Create(m_settings, m_settings.GetAllocator());
|
||||
setting = AZStd::move(store);
|
||||
SignalNotifier(path, Type::Object);
|
||||
auto anchorType = Type::NoType;
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
rapidjson::Value& setting = pointer.Create(m_settings, m_settings.GetAllocator());
|
||||
setting = AZStd::move(store);
|
||||
anchorType = SettingsRegistryImplInternal::RapidjsonToSettingsRegistryType(setting);
|
||||
}
|
||||
SignalNotifier(path, anchorType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -500,7 +528,7 @@ namespace AZ
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
// rapidjson::Pointer assets that the supplied string
|
||||
// rapidjson::Pointer asserts that the supplied string
|
||||
// is not nullptr even if the supplied size is 0
|
||||
// Setting to empty string to prevent assert
|
||||
path = "";
|
||||
@@ -605,7 +633,7 @@ namespace AZ
|
||||
return Set(key, value);
|
||||
}
|
||||
|
||||
bool SettingsRegistryImpl::MergeSettings(AZStd::string_view data, Format format)
|
||||
bool SettingsRegistryImpl::MergeSettings(AZStd::string_view data, Format format, AZStd::string_view anchorKey)
|
||||
{
|
||||
rapidjson::Document jsonPatch;
|
||||
constexpr int flags = rapidjson::kParseStopWhenDoneFlag | rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag;
|
||||
@@ -631,17 +659,43 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
|
||||
JsonSerializationResult::ResultCode mergeResult =
|
||||
JsonSerialization::ApplyPatch(m_settings, m_settings.GetAllocator(), jsonPatch, mergeApproach);
|
||||
if (mergeResult.GetProcessing() != JsonSerializationResult::Processing::Completed)
|
||||
rapidjson::Pointer anchorPath;
|
||||
if (!anchorKey.empty())
|
||||
{
|
||||
AZ_Error("Settings Registry", false, "Failed to fully merge data into registry.");
|
||||
return false;
|
||||
anchorPath = rapidjson::Pointer(anchorKey.data(), anchorKey.size());
|
||||
if (!anchorPath.IsValid())
|
||||
{
|
||||
rapidjson::Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-");
|
||||
AZ_Error("Settings Registry", false, R"(Anchor path "%.*s" is invalid.)", AZ_STRING_ARG(anchorKey));
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetObject()
|
||||
.AddMember(rapidjson::StringRef("Error"), rapidjson::StringRef("Invalid anchor key."), m_settings.GetAllocator())
|
||||
.AddMember(rapidjson::StringRef("Path"),
|
||||
rapidjson::Value(anchorKey.data(), aznumeric_caster(anchorKey.size()), m_settings.GetAllocator()),
|
||||
m_settings.GetAllocator());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SignalNotifier("", Type::Object);
|
||||
auto anchorType = AZ::SettingsRegistryInterface::Type::NoType;
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
rapidjson::Value& anchorRoot = anchorPath.IsValid() ? anchorPath.Create(m_settings, m_settings.GetAllocator())
|
||||
: m_settings;
|
||||
|
||||
JsonSerializationResult::ResultCode mergeResult =
|
||||
JsonSerialization::ApplyPatch(anchorRoot, m_settings.GetAllocator(), jsonPatch, mergeApproach);
|
||||
if (mergeResult.GetProcessing() != JsonSerializationResult::Processing::Completed)
|
||||
{
|
||||
AZ_Error("Settings Registry", false, "Failed to fully merge data into registry.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The settings have been successfully merged, query the type at the anchor key
|
||||
anchorType = SettingsRegistryImplInternal::RapidjsonToSettingsRegistryType(anchorRoot);
|
||||
}
|
||||
|
||||
SignalNotifier(anchorKey, anchorType);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1225,10 +1279,12 @@ namespace AZ
|
||||
ScopedMergeEvent scopedMergeEvent(m_preMergeEvent, m_postMergeEvent, path, rootKey);
|
||||
|
||||
JsonSerializationResult::ResultCode mergeResult(JsonSerializationResult::Tasks::Merge);
|
||||
auto anchorType = Type::NoType;
|
||||
if (rootKey.empty())
|
||||
{
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
mergeResult = JsonSerialization::ApplyPatch(m_settings, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings);
|
||||
anchorType = SettingsRegistryImplInternal::RapidjsonToSettingsRegistryType(m_settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1238,6 +1294,7 @@ namespace AZ
|
||||
AZStd::scoped_lock lock(m_settingMutex);
|
||||
Value& rootValue = root.Create(m_settings, m_settings.GetAllocator());
|
||||
mergeResult = JsonSerialization::ApplyPatch(rootValue, m_settings.GetAllocator(), jsonPatch, mergeApproach, m_applyPatchSettings);
|
||||
anchorType = SettingsRegistryImplInternal::RapidjsonToSettingsRegistryType(rootValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1265,7 +1322,7 @@ namespace AZ
|
||||
pointer.Create(m_settings, m_settings.GetAllocator()).SetString(path, m_settings.GetAllocator());
|
||||
}
|
||||
|
||||
SignalNotifier("", Type::Object);
|
||||
SignalNotifier(rootKey, anchorType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ namespace AZ
|
||||
Type GetType(AZStd::string_view path) const override;
|
||||
bool Visit(Visitor& visitor, AZStd::string_view path) const override;
|
||||
bool Visit(const VisitorCallback& callback, AZStd::string_view path) const override;
|
||||
[[nodiscard]] NotifyEventHandler RegisterNotifier(const NotifyCallback& callback) override;
|
||||
[[nodiscard]] NotifyEventHandler RegisterNotifier(NotifyCallback&& callback) override;
|
||||
[[nodiscard]] NotifyEventHandler RegisterNotifier(NotifyCallback callback) override;
|
||||
void RegisterNotifier(NotifyEventHandler& hanlder) override;
|
||||
void ClearNotifiers();
|
||||
|
||||
[[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) override;
|
||||
[[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) override;
|
||||
[[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) override;
|
||||
[[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) override;
|
||||
[[nodiscard]] PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback callback) override;
|
||||
void RegisterPreMergeEvent(PreMergeEventHandler& handler) override;
|
||||
[[nodiscard]] PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback callback) override;
|
||||
void RegisterPostMergeEvent(PostMergeEventHandler& handler) override;
|
||||
void ClearMergeEvents();
|
||||
|
||||
bool Get(bool& result, AZStd::string_view path) const override;
|
||||
@@ -76,13 +76,13 @@ namespace AZ
|
||||
|
||||
bool Remove(AZStd::string_view path) override;
|
||||
|
||||
bool MergeCommandLineArgument(AZStd::string_view argument, AZStd::string_view rootKey,
|
||||
bool MergeCommandLineArgument(AZStd::string_view argument, AZStd::string_view anchorKey,
|
||||
const CommandLineArgumentSettings& commandLineSettings) override;
|
||||
bool MergeSettings(AZStd::string_view data, Format format) override;
|
||||
bool MergeSettingsFile(AZStd::string_view path, Format format, AZStd::string_view rootKey,
|
||||
bool MergeSettings(AZStd::string_view data, Format format, AZStd::string_view anchorKey = "") override;
|
||||
bool MergeSettingsFile(AZStd::string_view path, Format format, AZStd::string_view anchorKey = "",
|
||||
AZStd::vector<char>* scratchBuffer = nullptr) override;
|
||||
bool MergeSettingsFolder(AZStd::string_view path, const Specializations& specializations,
|
||||
AZStd::string_view platform, AZStd::string_view rootKey = "", AZStd::vector<char>* scratchBuffer = nullptr) override;
|
||||
AZStd::string_view platform, AZStd::string_view anchorKey = "", AZStd::vector<char>* scratchBuffer = nullptr) override;
|
||||
|
||||
void SetApplyPatchSettings(const AZ::JsonApplyPatchSettings& applyPatchSettings) override;
|
||||
void GetApplyPatchSettings(AZ::JsonApplyPatchSettings& applyPatchSettings) override;
|
||||
@@ -121,6 +121,19 @@ namespace AZ
|
||||
PreMergeEvent m_preMergeEvent;
|
||||
PostMergeEvent m_postMergeEvent;
|
||||
|
||||
//! NOTE: During SignalNotifier, the registered notify event handlers are moved to a local NotifyEvent
|
||||
//! Therefore setting a value within the registry during signaling will queue future SignalNotifer calls
|
||||
//! These calls will then be invoked after the current signaling has completex
|
||||
//! This is done to avoid deadlock if another thread attempts to access register a notifier or signal one
|
||||
mutable AZStd::mutex m_signalMutex;
|
||||
struct SignalNotifierArgs
|
||||
{
|
||||
FixedValueString m_jsonPath;
|
||||
Type m_type;
|
||||
};
|
||||
AZStd::deque<SignalNotifierArgs> m_signalNotifierQueue;
|
||||
AZStd::atomic_int m_signalCount{};
|
||||
|
||||
rapidjson::Document m_settings;
|
||||
JsonSerializerSettings m_serializationSettings;
|
||||
JsonDeserializerSettings m_deserializationSettings;
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace AZ
|
||||
MOCK_CONST_METHOD1(GetType, Type(AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Visit, bool(Visitor&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Visit, bool(const VisitorCallback&, AZStd::string_view));
|
||||
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(const NotifyCallback&));
|
||||
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback&&));
|
||||
MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(const PreMergeEventCallback&));
|
||||
MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback&&));
|
||||
MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(const PostMergeEventCallback&));
|
||||
MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(PostMergeEventCallback&&));
|
||||
MOCK_METHOD1(RegisterNotifier, NotifyEventHandler(NotifyCallback));
|
||||
MOCK_METHOD1(RegisterNotifier, void(NotifyEventHandler&));
|
||||
MOCK_METHOD1(RegisterPreMergeEvent, PreMergeEventHandler(PreMergeEventCallback));
|
||||
MOCK_METHOD1(RegisterPreMergeEvent, void(PreMergeEventHandler&));
|
||||
MOCK_METHOD1(RegisterPostMergeEvent, PostMergeEventHandler(PostMergeEventCallback));
|
||||
MOCK_METHOD1(RegisterPostMergeEvent, void(PostMergeEventHandler&));
|
||||
|
||||
MOCK_CONST_METHOD2(Get, bool(bool&, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(Get, bool(s64&, AZStd::string_view));
|
||||
@@ -49,7 +49,7 @@ namespace AZ
|
||||
MOCK_METHOD1(Remove, bool(AZStd::string_view));
|
||||
|
||||
MOCK_METHOD3(MergeCommandLineArgument, bool(AZStd::string_view, AZStd::string_view, const CommandLineArgumentSettings&));
|
||||
MOCK_METHOD2(MergeSettings, bool(AZStd::string_view, Format));
|
||||
MOCK_METHOD3(MergeSettings, bool(AZStd::string_view, Format, AZStd::string_view));
|
||||
MOCK_METHOD4(MergeSettingsFile, bool(AZStd::string_view, Format, AZStd::string_view, AZStd::vector<char>*));
|
||||
MOCK_METHOD5(
|
||||
MergeSettingsFolder,
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
@@ -17,6 +17,11 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int StackConverter::FromNative(StackFrame*, unsigned int, void*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SymbolStorage::LoadModuleData(const void*, unsigned int)
|
||||
{}
|
||||
|
||||
|
||||
@@ -78,6 +78,12 @@ StackRecorder::Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int StackConverter::FromNative([[maybe_unused]] StackFrame* frames, [[maybe_unused]] unsigned int maxNumOfFrames, [[maybe_unused]] void* nativeContext)
|
||||
{
|
||||
AZ_Assert(false, "StackConverter::FromNative() is not supported for UnixLike platform yet");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SymbolStorage::DecodeFrames(const StackFrame* frames, unsigned int numFrames, StackLine* textLines)
|
||||
{
|
||||
|
||||
@@ -1048,9 +1048,9 @@ cleanup:
|
||||
unsigned int
|
||||
StackRecorder::Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned int suppressCount, void* nativeThread)
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
unsigned int numFrames = 0;
|
||||
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
if (nativeThread == NULL)
|
||||
{
|
||||
++suppressCount; // Skip current call
|
||||
@@ -1079,9 +1079,8 @@ cleanup:
|
||||
|
||||
STACKFRAME64 sf;
|
||||
memset(&sf, 0, sizeof(STACKFRAME64));
|
||||
DWORD imageType;
|
||||
DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
|
||||
|
||||
imageType = IMAGE_FILE_MACHINE_AMD64;
|
||||
sf.AddrPC.Offset = context.Rip;
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Offset = context.Rsp;
|
||||
@@ -1090,8 +1089,7 @@ cleanup:
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
EnterCriticalSection(&g_csDbgHelpDll);
|
||||
s32 frame = -(s32)suppressCount;
|
||||
for (; frame < (s32)maxNumOfFrames; ++frame)
|
||||
for (s32 frame = -static_cast<s32>(suppressCount); frame < static_cast<s32>(maxNumOfFrames); ++frame)
|
||||
{
|
||||
if (!g_StackWalk64(imageType, g_currentProcess, hThread, &sf, &context, 0, g_SymFunctionTableAccess64, g_SymGetModuleBase64, 0))
|
||||
{
|
||||
@@ -1111,15 +1109,68 @@ cleanup:
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&g_csDbgHelpDll);
|
||||
}
|
||||
return numFrames;
|
||||
}
|
||||
#else
|
||||
(void)frames;
|
||||
(void)maxNumOfFrames;
|
||||
(void)suppressCount;
|
||||
(void)nativeThread;
|
||||
return 0;
|
||||
AZ_UNUSED(frames);
|
||||
AZ_UNUSED(maxNumOfFrames);
|
||||
AZ_UNUSED(suppressCount);
|
||||
AZ_UNUSED(nativeThread);
|
||||
#endif // AZ_ENABLE_DEBUG_TOOLS
|
||||
|
||||
return numFrames;
|
||||
}
|
||||
|
||||
unsigned int StackConverter::FromNative(StackFrame* frames, unsigned int maxNumOfFrames, void* nativeContext)
|
||||
{
|
||||
unsigned int numFrames = 0;
|
||||
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
if (!g_dbgHelpLoaded)
|
||||
{
|
||||
LoadDbgHelp();
|
||||
}
|
||||
|
||||
HANDLE hThread;
|
||||
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
PCONTEXT nativeContextType = reinterpret_cast<PCONTEXT>(nativeContext);
|
||||
STACKFRAME64 sf;
|
||||
memset(&sf, 0, sizeof(STACKFRAME64));
|
||||
|
||||
DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
|
||||
|
||||
sf.AddrPC.Offset = nativeContextType->Rip;
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Offset = nativeContextType->Rsp;
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
sf.AddrStack.Offset = nativeContextType->Rsp;
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
EnterCriticalSection(&g_csDbgHelpDll);
|
||||
for (unsigned int frame = 0; frame < maxNumOfFrames; ++frame)
|
||||
{
|
||||
if (!g_StackWalk64(imageType, g_currentProcess, hThread, &sf, nativeContext, 0, g_SymFunctionTableAccess64, g_SymGetModuleBase64, 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (sf.AddrPC.Offset == sf.AddrReturn.Offset)
|
||||
{
|
||||
// "StackWalk64-Endless-Callstack!"
|
||||
break;
|
||||
}
|
||||
|
||||
frames[numFrames++].m_programCounter = sf.AddrPC.Offset;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&g_csDbgHelpDll);
|
||||
#else
|
||||
AZ_UNUSED(frames);
|
||||
AZ_UNUSED(maxNumOfFrames);
|
||||
AZ_UNUSED(nativeContext);
|
||||
#endif
|
||||
|
||||
return numFrames;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1413,7 +1413,7 @@ namespace UnitTest
|
||||
>;
|
||||
TYPED_TEST_CASE(HashedSetDifferentAllocatorFixture, SetTemplateConfigs);
|
||||
|
||||
#if GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TYPED_TEST(HashedSetDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
|
||||
{
|
||||
using ContainerType = typename TypeParam::ContainerType;
|
||||
@@ -1435,7 +1435,7 @@ namespace UnitTest
|
||||
}
|
||||
}, ".*");
|
||||
}
|
||||
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
template<typename ContainerType>
|
||||
class HashedMapContainers
|
||||
@@ -1811,7 +1811,7 @@ namespace UnitTest
|
||||
>;
|
||||
TYPED_TEST_CASE(HashedMapDifferentAllocatorFixture, MapTemplateConfigs);
|
||||
|
||||
#if GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TYPED_TEST(HashedMapDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
|
||||
{
|
||||
using ContainerType = typename TypeParam::ContainerType;
|
||||
@@ -1833,7 +1833,7 @@ namespace UnitTest
|
||||
}
|
||||
} , ".*");
|
||||
}
|
||||
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
namespace HashedContainerTransparentTestInternal
|
||||
{
|
||||
|
||||
@@ -1095,7 +1095,7 @@ namespace UnitTest
|
||||
>;
|
||||
TYPED_TEST_CASE(TreeSetDifferentAllocatorFixture, SetTemplateConfigs);
|
||||
|
||||
#if GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TYPED_TEST(TreeSetDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
|
||||
{
|
||||
using ContainerType = typename TypeParam::ContainerType;
|
||||
@@ -1117,7 +1117,7 @@ namespace UnitTest
|
||||
}
|
||||
}, ".*");
|
||||
}
|
||||
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
TYPED_TEST(TreeSetDifferentAllocatorFixture, SwapMovesElementsWhenAllocatorsDiffer)
|
||||
{
|
||||
@@ -1516,7 +1516,7 @@ namespace UnitTest
|
||||
>;
|
||||
TYPED_TEST_CASE(TreeMapDifferentAllocatorFixture, MapTemplateConfigs);
|
||||
|
||||
#if GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TYPED_TEST(TreeMapDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
|
||||
{
|
||||
using ContainerType = typename TypeParam::ContainerType;
|
||||
@@ -1538,7 +1538,7 @@ namespace UnitTest
|
||||
}
|
||||
}, ".*");
|
||||
}
|
||||
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
TYPED_TEST(TreeMapDifferentAllocatorFixture, SwapMovesElementsWhenAllocatorsDiffer)
|
||||
{
|
||||
|
||||
@@ -1595,7 +1595,7 @@ namespace UnitTest
|
||||
}
|
||||
};
|
||||
|
||||
#if GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#if GTEST_HAS_DEATH_TEST
|
||||
TEST_F(ThreadEventsDeathTest, UsingClientBus_AvoidsDeadlock)
|
||||
{
|
||||
EXPECT_EXIT(
|
||||
@@ -1608,5 +1608,5 @@ namespace UnitTest
|
||||
, ::testing::ExitedWithCode(0),".*");
|
||||
|
||||
}
|
||||
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user