Merge branch 'development' of https://github.com/o3de/o3de into jckand/DynVegXfailFixes
This commit is contained in:
@@ -1,73 +0,0 @@
|
||||
---
|
||||
name: RFC Feature request
|
||||
about: Create Feature RFC for this project
|
||||
title: Proposed RFC Feature =description=
|
||||
labels: 'rfc-feature'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# O3DE RFC Feature Template
|
||||
|
||||
### When using this template, you do not have to fill out every question below. The questions are there for guidance.
|
||||
|
||||
This RFC feature template should be used for any feature that is not a bug or a substantial reorganization of the O3DE product.
|
||||
|
||||
If you submit a pull request to implement a new feature without going through the RFC process, it may be closed with a polite request to submit an RFC first.
|
||||
|
||||
A hastily proposed RFC can hurt its chances of acceptance. Low-quality proposals, proposals for previously-rejected features, or those that don't fit into the near-term roadmap may be quickly rejected, demotivating the unprepared contributor. Laying some groundwork ahead of the RFC can make the process smoother.
|
||||
|
||||
Although there is no single way to prepare for submitting an RFC, it is generally a good idea to pursue feedback from other project developers beforehand to ascertain that the RFC may be desirable; having a consistent impact on the project requires concerted effort toward consensus-building.
|
||||
|
||||
The most common preparations for writing and submitting an RFC include:
|
||||
- Talking the idea over on our Discord server.
|
||||
- Discussing the topic on our GitHub RFCs discussions page.
|
||||
- Occasionally posting "pre-RFCs" on the GitHub RFCs discussion page.
|
||||
You may file issues in the RFCs repo for discussion, but these are not actively looked at by the teams.
|
||||
|
||||
As a rule of thumb, receiving encouraging feedback from long-standing project developers, and particularly members of the relevant sub-team, is a good indication that the RFC is worth pursuing.
|
||||
|
||||
# ----- DELETE EVERYTHING FROM THE TOP TO THE SUMMARY LINE BELOW WHEN USING TEMPLATE ----- #
|
||||
|
||||
### Summary:
|
||||
Single paragraph explanation of the feature
|
||||
|
||||
### What is the relevance of this feature?
|
||||
Why is this important? What are the use cases? What will it do once completed?
|
||||
|
||||
### Feature design description:
|
||||
- Explain the design of the feature with enough detail that someone familiar with the environment and framework can understand the concept and explain it to others.
|
||||
- It should include at least one end-to-end example of how a developer will use it along with specific details, including outlying use cases.
|
||||
|
||||
- If there is any new terminology, it should be defined here.
|
||||
|
||||
### Technical design description:
|
||||
- Explain the technical portion of the work in enough detail that members can implement the feature.
|
||||
|
||||
- Explain any API or process changes required to implement this feature
|
||||
|
||||
- This section should relate to the feature design description by reference and explain in greater detail how it makes the feature design examples work.
|
||||
|
||||
- This should also provide detailed information on compatibility with different hardware platforms.
|
||||
|
||||
|
||||
### What are the advantages of the feature?
|
||||
- Explain the advantages for someone to use this feature
|
||||
|
||||
### What are the disadvantages of the feature?
|
||||
- Explain any disadvantages for someone to use this feature
|
||||
|
||||
### How will this be implemented or integrated into the O3DE environment?
|
||||
- Explain how a developer will integrate this into the codebase of O3DE and provide any specific library or technical stack requirements.
|
||||
|
||||
### Are there any alternatives to this feature?
|
||||
- Provide any other designs that have been considered. Explain what the impact might be of not doing this.
|
||||
- If there is any prior art or approaches with other frameworks in the same domain, explain how they may have solved this problem or implemented this feature.
|
||||
|
||||
### How will users learn this feature?
|
||||
- Detail how it can be best presented and how it is used as an extension or a standalone tool used with O3DE.
|
||||
- Explain if and how it may change how individuals would use the platform and if any documentation must be changed or reorganized.
|
||||
- Explain how it would be taught to new and existing O3DE users.
|
||||
|
||||
### Are there any open questions?
|
||||
- What are some of the open questions and potential scenarios that should be considered?
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: RFC Suggestion request
|
||||
about: Create Suggestion RFC for this project
|
||||
title: Proposed RFC Suggestion =description=
|
||||
labels: 'rfc-suggestion'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# O3DE Suggestion RFC Template
|
||||
|
||||
### When using this template, you do not have to fill out every question below. The questions are there for guidance.
|
||||
|
||||
This RFC template should be used for any suggestion that is not based upon code or content related to the O3DE product itself. This template is for proposing new process models, approaches, or ideas to improve the O3DE community.
|
||||
|
||||
A hastily proposed RFC can hurt its chances of acceptance. Low-quality proposals, proposals for previously rejected features, or those that do not have any substantive value to the project may be quickly rejected, demotivating the unprepared contributor. Laying some groundwork with others in the community ahead of the RFC can make the process much smoother.
|
||||
|
||||
Although there is no single way to prepare for submitting an RFC, it is generally a good idea to pursue feedback from other project members beforehand. Keep in mind that you want other members to contribute and back your suggestion, which can drastically improve the chances of implementation.
|
||||
|
||||
The most common preparations for writing and submitting an RFC include:
|
||||
- Talking the idea over on our Discord server.
|
||||
- Creating a discussion on our GitHub RFCs discussions page.
|
||||
- Occasionally posting "pre-RFCs" on the GitHub RFCs discussion page.
|
||||
You may file issues in the RFCs repo for discussion, but these are not actively looked at by the teams.
|
||||
|
||||
As a rule of thumb, receiving encouraging feedback from long-standing community members is a good indication that the RFC is worth pursuing.
|
||||
|
||||
# ----- DELETE EVERYTHING FROM THE TOP TO THE SUMMARY LINE BELOW WHEN USING TEMPLATE ----- #
|
||||
|
||||
### Summary:
|
||||
Single paragraph explanation of the suggestion
|
||||
|
||||
### What is the motivation for this suggestion?
|
||||
Why is this important?
|
||||
What are the use cases for this suggestion?
|
||||
What should the outcome be if this suggestion is implemented?
|
||||
|
||||
### Suggestion design description:
|
||||
- Explain the suggestion with enough detail that someone familiar with the process and environment of the project can understand the suggestion and explain it to others.
|
||||
- It should include at least one end-to-end example of how the community will use it along with the specific details with outlying use cases.
|
||||
|
||||
- If there is any new terminology, it should be defined here.
|
||||
|
||||
### What are the advantages of the suggestion?
|
||||
- Explain the advantages of using this suggestion
|
||||
|
||||
### What are the disadvantages of the suggestion?
|
||||
- Explain any disadvantages or trade-offs to using this suggestion
|
||||
|
||||
### How will this be work within the O3DE project?
|
||||
- Explain how this suggestion will be work within the O3DE project.
|
||||
|
||||
### Are there any alternatives to this suggestion?
|
||||
- Provide any other alternative ways that have been considered.
|
||||
- Explain what the impact might be of not implementing this suggestion.
|
||||
- If there are other similar suggestions previously used, list them and explain which parts may have solved some or all of this problem.
|
||||
|
||||
### What is the strategy for adoption?
|
||||
- Explain how new and existing users will adopt this suggestion.
|
||||
- Point out any efforts needed if it requires coordination with multiple SIGs or other projects.
|
||||
- Explain how it would be taught to new and existing O3DE users.
|
||||
@@ -47,8 +47,7 @@ set(ENABLED_GEMS
|
||||
LmbrCentral
|
||||
LyShine
|
||||
HttpRequestor
|
||||
Atom_AtomBridge
|
||||
PythonCoverage
|
||||
Atom
|
||||
AWSCore
|
||||
AWSClientAuth
|
||||
AWSMetrics
|
||||
|
||||
+5
-8
@@ -15,10 +15,7 @@ import ly_test_tools.log.log_monitor
|
||||
|
||||
# fixture imports
|
||||
from AWS.Windows.resource_mappings.resource_mappings import resource_mappings
|
||||
from AWS.Windows.cdk.cdk_utils import Cdk
|
||||
from AWS.common.aws_utils import AwsUtils
|
||||
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor as asset_processor
|
||||
from AWS.common.aws_credentials import aws_credentials
|
||||
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
|
||||
from .aws_metrics_utils import aws_metrics_utils
|
||||
|
||||
AWS_METRICS_FEATURE_NAME = 'AWSMetrics'
|
||||
@@ -28,7 +25,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(launcher: ly_test_tools.launchers.Launcher,
|
||||
cdk: Cdk,
|
||||
cdk: pytest.fixture,
|
||||
asset_processor: asset_processor,
|
||||
resource_mappings: resource_mappings,
|
||||
context_variable: str = '') -> typing.Tuple[ly_test_tools.log.log_monitor.LogMonitor, str, str]:
|
||||
@@ -119,7 +116,7 @@ class TestAWSMetricsWindows(object):
|
||||
asset_processor: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
aws_utils: pytest.fixture,
|
||||
aws_credentials: aws_credentials,
|
||||
aws_credentials: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
cdk: pytest.fixture,
|
||||
aws_metrics_utils: aws_metrics_utils,
|
||||
@@ -162,7 +159,7 @@ class TestAWSMetricsWindows(object):
|
||||
level: str,
|
||||
launcher: ly_test_tools.launchers.Launcher,
|
||||
cdk: pytest.fixture,
|
||||
aws_credentials: aws_credentials,
|
||||
aws_credentials: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
workspace: pytest.fixture):
|
||||
@@ -187,7 +184,7 @@ class TestAWSMetricsWindows(object):
|
||||
level: str,
|
||||
launcher: ly_test_tools.launchers.Launcher,
|
||||
cdk: pytest.fixture,
|
||||
aws_credentials: aws_credentials,
|
||||
aws_credentials: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
aws_utils: pytest.fixture,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
@@ -0,0 +1,186 @@
|
||||
"""
|
||||
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
|
||||
import logging
|
||||
import time
|
||||
|
||||
import pytest
|
||||
import ly_test_tools
|
||||
import ly_test_tools.log.log_monitor
|
||||
import ly_test_tools.environment.process_utils as process_utils
|
||||
import ly_test_tools.o3de.asset_processor_utils as asset_processor_utils
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from AWS.Windows.resource_mappings.resource_mappings import resource_mappings
|
||||
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
|
||||
|
||||
AWS_CORE_FEATURE_NAME = 'AWSCore'
|
||||
AWS_RESOURCE_MAPPING_FILE_NAME = 'default_aws_resource_mappings.json'
|
||||
|
||||
process_utils.kill_processes_named("o3de", ignore_extensions=True) # Kill ProjectManager windows
|
||||
|
||||
GAME_LOG_NAME = 'Game.log'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(launcher: pytest.fixture, cdk: pytest.fixture, resource_mappings: pytest.fixture, asset_processor: pytest.fixture):
|
||||
asset_processor_utils.kill_asset_processor()
|
||||
logger.info(f'Cdk stack names:\n{cdk.list()}')
|
||||
stacks = cdk.deploy(additonal_params=['--all'])
|
||||
resource_mappings.populate_output_keys(stacks)
|
||||
asset_processor.start()
|
||||
asset_processor.wait_for_idle()
|
||||
|
||||
file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), GAME_LOG_NAME)
|
||||
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
|
||||
|
||||
return log_monitor
|
||||
|
||||
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.usefixtures('automatic_process_killer')
|
||||
@pytest.mark.usefixtures('asset_processor')
|
||||
@pytest.mark.usefixtures('cdk')
|
||||
@pytest.mark.parametrize('feature_name', [AWS_CORE_FEATURE_NAME])
|
||||
@pytest.mark.parametrize('region_name', ['us-west-2'])
|
||||
@pytest.mark.parametrize('assume_role_arn', ['arn:aws:iam::645075835648:role/o3de-automation-tests'])
|
||||
@pytest.mark.parametrize('session_name', ['o3de-Automation-session'])
|
||||
@pytest.mark.usefixtures('workspace')
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['AWS/Core'])
|
||||
@pytest.mark.usefixtures('resource_mappings')
|
||||
@pytest.mark.parametrize('resource_mappings_filename', [AWS_RESOURCE_MAPPING_FILE_NAME])
|
||||
@pytest.mark.usefixtures('aws_credentials')
|
||||
@pytest.mark.parametrize('profile_name', ['AWSAutomationTest'])
|
||||
class TestAWSCoreAWSResourceInteraction(object):
|
||||
"""
|
||||
Test class to verify AWSCore can downloading a file from S3.
|
||||
"""
|
||||
def test_download_from_s3(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
cdk: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
resource_mappings: pytest.fixture
|
||||
):
|
||||
"""
|
||||
Setup: Deploys cdk and updates resource mapping file.
|
||||
Tests: Getting AWS credentials for no signed in user.
|
||||
Verification: Log monitor looks for success download. The existence and contents of the file are also verified.
|
||||
"""
|
||||
|
||||
log_monitor = setup(launcher, cdk, resource_mappings, asset_processor)
|
||||
|
||||
launcher.args = ['+LoadLevel', level]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
|
||||
user_dir = os.path.join(workspace.paths.project(), 'user')
|
||||
download_dir = os.path.join(user_dir, 's3_download')
|
||||
if not os.path.exists(download_dir):
|
||||
os.makedirs(download_dir)
|
||||
|
||||
with launcher.start(launch_ap=False):
|
||||
result = log_monitor.monitor_log_for_lines(
|
||||
expected_lines=['(Script) - [S3] Head object request is done',
|
||||
'(Script) - [S3] Head object success: Object example.txt is found.',
|
||||
'(Script) - [S3] Get object success: Object example.txt is downloaded.'],
|
||||
unexpected_lines=['(Script) - [S3] Head object error: No response body.',
|
||||
'(Script) - [S3] Get object error: Request validation failed, output file directory doesn\'t exist.'],
|
||||
halt_on_unexpected=True
|
||||
)
|
||||
|
||||
assert result, "Expected lines weren't found."
|
||||
|
||||
download_path = os.path.join(download_dir, 'output.txt')
|
||||
|
||||
file_was_downloaded = os.path.exists(download_path)
|
||||
# clean up the file directories.
|
||||
if file_was_downloaded:
|
||||
os.remove(download_path)
|
||||
os.rmdir(download_dir)
|
||||
|
||||
assert file_was_downloaded, 'The expected file wasn\'t successfully downloaded'
|
||||
|
||||
def test_invoke_lambda(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
cdk: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
asset_processor: pytest.fixture
|
||||
):
|
||||
"""
|
||||
Setup: Deploys the CDK.
|
||||
Tests: Runs the test level.
|
||||
Verification: Searches the logs for the expected output from the example lambda.
|
||||
"""
|
||||
|
||||
log_monitor = setup(launcher, cdk, resource_mappings, asset_processor)
|
||||
|
||||
launcher.args = ['+LoadLevel', level]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
|
||||
with launcher.start(launch_ap=False):
|
||||
result = log_monitor.monitor_log_for_lines(
|
||||
expected_lines=['(Script) - [Lambda] Completed Invoke',
|
||||
'(Script) - [Lambda] Invoke success: {"statusCode": 200, "body": {}}'],
|
||||
unexpected_lines=['(Script) - Request validation failed, output file miss full path.',
|
||||
'(Script) - '],
|
||||
halt_on_unexpected=True
|
||||
)
|
||||
|
||||
assert result
|
||||
|
||||
def test_get_dynamodb_value(self,
|
||||
level: str,
|
||||
launcher: pytest.fixture,
|
||||
cdk: pytest.fixture,
|
||||
resource_mappings: pytest.fixture,
|
||||
workspace: pytest.fixture,
|
||||
asset_processor: pytest.fixture,
|
||||
aws_utils: pytest.fixture,
|
||||
):
|
||||
"""
|
||||
Setup: Deploys the CDK application
|
||||
Test: Runs a launcher with a level that loads a scriptcanvas that pulls a DynamoDB table value.
|
||||
Verification: The value is output in the logs and verified by the test.
|
||||
"""
|
||||
|
||||
def write_test_table_data():
|
||||
client = aws_utils.client('dynamodb')
|
||||
table_name = resource_mappings.get_resource_name_id("AWSCore.ExampleDynamoTableOutput")
|
||||
try:
|
||||
client.put_item(
|
||||
TableName=table_name,
|
||||
Item={
|
||||
'id': {
|
||||
'S': 'Item1'
|
||||
}
|
||||
}
|
||||
)
|
||||
logger.info(f'Loaded data into table {table_name}')
|
||||
except ClientError:
|
||||
logger.exception(f'Failed to load data into table {table_name}')
|
||||
raise
|
||||
|
||||
log_monitor = setup(launcher, cdk, resource_mappings, asset_processor)
|
||||
write_test_table_data()
|
||||
|
||||
launcher.args = ['+LoadLevel', level]
|
||||
launcher.args.extend(['-rhi=null'])
|
||||
|
||||
with launcher.start(launch_ap=False):
|
||||
result = log_monitor.monitor_log_for_lines(
|
||||
expected_lines=['(Script) - [DynamoDB] Results finished'],
|
||||
unexpected_lines=['(Script) - Request validation failed, output file miss full path.',
|
||||
'(Script) - '],
|
||||
halt_on_unexpected=True
|
||||
)
|
||||
|
||||
assert result
|
||||
@@ -107,24 +107,3 @@ class AwsCredentials:
|
||||
else:
|
||||
self._credentials[self._profile_name][attribute_name] = attribute_value
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def aws_credentials(request: pytest.fixture, aws_utils: pytest.fixture, profile_name: str):
|
||||
"""
|
||||
Fixture for setting up temporary AWS credentials from assume role.
|
||||
|
||||
:param request: _pytest.fixtures.SubRequest class that handles getting
|
||||
a pytest fixture from a pytest function/fixture.
|
||||
:param aws_utils: aws_utils fixture.
|
||||
:param profile_name: Named AWS profile to store temporary credentials.
|
||||
"""
|
||||
aws_credentials_obj = AwsCredentials(profile_name)
|
||||
original_access_key, original_secret_access_key, original_token = aws_credentials_obj.get_aws_credentials()
|
||||
aws_credentials_obj.set_aws_credentials_by_session(aws_utils.assume_session())
|
||||
|
||||
def teardown():
|
||||
# Reset to the named profile using the original AWS credentials
|
||||
aws_credentials_obj.set_aws_credentials(original_access_key, original_secret_access_key, original_token)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return aws_credentials_obj
|
||||
|
||||
@@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
import pytest
|
||||
import logging
|
||||
from AWS.common.aws_utils import AwsUtils
|
||||
from AWS.common.aws_credentials import AwsCredentials
|
||||
from AWS.Windows.cdk.cdk_utils import Cdk
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -81,3 +82,26 @@ def cdk(
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return pytest.cdk_obj
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def aws_credentials(request: pytest.fixture, aws_utils: pytest.fixture, profile_name: str):
|
||||
"""
|
||||
Fixture for setting up temporary AWS credentials from assume role.
|
||||
|
||||
:param request: _pytest.fixtures.SubRequest class that handles getting
|
||||
a pytest fixture from a pytest function/fixture.
|
||||
:param aws_utils: aws_utils fixture.
|
||||
:param profile_name: Named AWS profile to store temporary credentials.
|
||||
"""
|
||||
aws_credentials_obj = AwsCredentials(profile_name)
|
||||
original_access_key, original_secret_access_key, original_token = aws_credentials_obj.get_aws_credentials()
|
||||
aws_credentials_obj.set_aws_credentials_by_session(aws_utils.assume_session())
|
||||
|
||||
def teardown():
|
||||
# Reset to the named profile using the original AWS credentials
|
||||
aws_credentials_obj.set_aws_credentials(original_access_key, original_secret_access_key, original_token)
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
return aws_credentials_obj
|
||||
|
||||
@@ -38,7 +38,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
|
||||
TEST_SUITE main
|
||||
TEST_REQUIRES gpu
|
||||
TEST_SERIAL
|
||||
TIMEOUT 400
|
||||
TIMEOUT 800
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_GPUTests.py
|
||||
RUNTIME_DEPENDENCIES
|
||||
AssetProcessor
|
||||
|
||||
@@ -17,7 +17,7 @@ import editor_python_test_tools.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots'
|
||||
EDITOR_TIMEOUT = 300
|
||||
EDITOR_TIMEOUT = 600
|
||||
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ class TestAllComponentsIndepthTests(object):
|
||||
unexpected_lines=unexpected_lines,
|
||||
halt_on_unexpected=True,
|
||||
cfg_args=[level],
|
||||
auto_test_mode=False,
|
||||
null_renderer=False,
|
||||
)
|
||||
|
||||
|
||||
@@ -60,24 +60,7 @@ class TestEditMenuOptions(EditorTestHelper):
|
||||
("Modify", "Transform Mode", "Rotate"),
|
||||
("Modify", "Transform Mode", "Scale"),
|
||||
("Editor Settings", "Global Preferences"),
|
||||
("Editor Settings", "Graphics Settings"),
|
||||
("Editor Settings", "Editor Settings Manager"),
|
||||
("Editor Settings", "Graphics Performance", "PC", "Very High"),
|
||||
("Editor Settings", "Graphics Performance", "PC", "High"),
|
||||
("Editor Settings", "Graphics Performance", "PC", "Medium"),
|
||||
("Editor Settings", "Graphics Performance", "PC", "Low"),
|
||||
("Editor Settings", "Graphics Performance", "OSX Metal", "Very High"),
|
||||
("Editor Settings", "Graphics Performance", "OSX Metal", "High"),
|
||||
("Editor Settings", "Graphics Performance", "OSX Metal", "Medium"),
|
||||
("Editor Settings", "Graphics Performance", "OSX Metal", "Low"),
|
||||
("Editor Settings", "Graphics Performance", "Android", "Very High"),
|
||||
("Editor Settings", "Graphics Performance", "Android", "High"),
|
||||
("Editor Settings", "Graphics Performance", "Android", "Medium"),
|
||||
("Editor Settings", "Graphics Performance", "Android", "Low"),
|
||||
("Editor Settings", "Graphics Performance", "iOS", "Very High"),
|
||||
("Editor Settings", "Graphics Performance", "iOS", "High"),
|
||||
("Editor Settings", "Graphics Performance", "iOS", "Medium"),
|
||||
("Editor Settings", "Graphics Performance", "iOS", "Low"),
|
||||
("Editor Settings", "Keyboard Customization", "Customize Keyboard"),
|
||||
("Editor Settings", "Keyboard Customization", "Export Keyboard Settings"),
|
||||
("Editor Settings", "Keyboard Customization", "Import Keyboard Settings"),
|
||||
|
||||
@@ -55,12 +55,7 @@ class TestMenus(object):
|
||||
"Rotate Action triggered",
|
||||
"Scale Action triggered",
|
||||
"Global Preferences Action triggered",
|
||||
"Graphics Settings Action triggered",
|
||||
"Editor Settings Manager Action triggered",
|
||||
"Very High Action triggered",
|
||||
"High Action triggered",
|
||||
"Medium Action triggered",
|
||||
"Low Action triggered",
|
||||
"Customize Keyboard Action triggered",
|
||||
"Export Keyboard Settings Action triggered",
|
||||
"Import Keyboard Settings Action triggered",
|
||||
|
||||
@@ -51,4 +51,18 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
AutomatedTesting.GameLauncher
|
||||
AutomatedTesting.Assets
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::GameLauncherWithGPU
|
||||
TEST_SUITE sandbox
|
||||
TEST_REQUIRES gpu
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/test_GameLauncher_EnterExitGameMode_Works.py
|
||||
TIMEOUT 100
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
AZ::PythonBindingsExample
|
||||
Legacy::Editor
|
||||
AutomatedTesting.GameLauncher
|
||||
AutomatedTesting.Assets
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5242a9b598bc329ef2af2b114092e4e50c7c398cdde4605a0717b0b3ce66d797
|
||||
size 10030
|
||||
@@ -0,0 +1,6 @@
|
||||
<download name="Core" type="Map">
|
||||
<index src="filelist.xml" dest="filelist.xml"/>
|
||||
<files>
|
||||
<file src="level.pak" dest="level.pak" size="EBE" md5="2b5b16a34ef2c8f62956dfb5588c4578"/>
|
||||
</files>
|
||||
</download>
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4ba2f409fc974c72b8ee8b660d200ed1d013ee8408419b0e91d6d487e71e4997
|
||||
size 3774
|
||||
@@ -0,0 +1,12 @@
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
0,0,0,0,0,0
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -111,7 +111,6 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
Gem::LmbrCentral.Static
|
||||
Legacy::NewsShared
|
||||
AZ::AWSNativeSDKInit
|
||||
AZ::AtomCore
|
||||
Gem::Atom_RPI.Edit
|
||||
@@ -139,7 +138,6 @@ ly_add_source_properties(
|
||||
ly_add_source_properties(
|
||||
SOURCES
|
||||
Core/LevelEditorMenuHandler.cpp
|
||||
GraphicsSettingsDialog.cpp
|
||||
MainWindow.cpp
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
VALUES ${LY_PAL_TOOLS_DEFINES}
|
||||
|
||||
@@ -497,9 +497,15 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
|
||||
// Hide Selection
|
||||
editMenu.AddAction(AzToolsFramework::HideSelection);
|
||||
|
||||
// Unhide All
|
||||
// Show All
|
||||
editMenu.AddAction(AzToolsFramework::ShowAll);
|
||||
|
||||
// Lock Selection
|
||||
editMenu.AddAction(AzToolsFramework::LockSelection);
|
||||
|
||||
// UnLock All
|
||||
editMenu.AddAction(AzToolsFramework::UnlockAll);
|
||||
|
||||
/*
|
||||
* The following block of code is part of the feature "Isolation Mode" and is temporarily
|
||||
* disabled for 1.10 release.
|
||||
@@ -552,49 +558,9 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
|
||||
// Global Preferences...
|
||||
editorSettingsMenu.AddAction(ID_TOOLS_PREFERENCES);
|
||||
|
||||
// Graphics Settings...
|
||||
editorSettingsMenu.AddAction(ID_GRAPHICS_SETTINGS);
|
||||
|
||||
// Editor Settings Manager
|
||||
AddOpenViewPaneAction(editorSettingsMenu, LyViewPane::EditorSettingsManager);
|
||||
|
||||
// Graphics Performance
|
||||
auto graphicPerformanceSubMenu = editorSettingsMenu.AddMenu(QObject::tr("Graphics Performance"));
|
||||
|
||||
auto pcMenu = graphicPerformanceSubMenu.AddMenu(tr("PC"));
|
||||
pcMenu.AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC);
|
||||
pcMenu.AddAction(ID_GAME_PC_ENABLEHIGHSPEC);
|
||||
pcMenu.AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC);
|
||||
pcMenu.AddAction(ID_GAME_PC_ENABLELOWSPEC);
|
||||
|
||||
auto osxmetalMenu = graphicPerformanceSubMenu.AddMenu(tr("OSX Metal"));
|
||||
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC);
|
||||
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC);
|
||||
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC);
|
||||
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC);
|
||||
|
||||
auto androidMenu = graphicPerformanceSubMenu.AddMenu(tr("Android"));
|
||||
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC);
|
||||
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC);
|
||||
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC);
|
||||
androidMenu.AddAction(ID_GAME_ANDROID_ENABLELOWSPEC);
|
||||
|
||||
auto iosMenu = graphicPerformanceSubMenu.AddMenu(tr("iOS"));
|
||||
iosMenu.AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC);
|
||||
iosMenu.AddAction(ID_GAME_IOS_ENABLEHIGHSPEC);
|
||||
iosMenu.AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC);
|
||||
iosMenu.AddAction(ID_GAME_IOS_ENABLELOWSPEC);
|
||||
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
|
||||
auto publicname##Menu = graphicPerformanceSubMenu.AddMenu(tr(PublicAuxName2));\
|
||||
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEHIGHSPEC);\
|
||||
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC);\
|
||||
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLELOWSPEC);
|
||||
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
|
||||
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
|
||||
#endif
|
||||
|
||||
// Keyboard Customization
|
||||
auto keyboardCustomizationMenu = editorSettingsMenu.AddMenu(tr("Keyboard Customization"));
|
||||
keyboardCustomizationMenu.AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD);
|
||||
|
||||
@@ -111,7 +111,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "ToolBox.h"
|
||||
#include "LevelInfo.h"
|
||||
#include "EditorPreferencesDialog.h"
|
||||
#include "GraphicsSettingsDialog.h"
|
||||
#include "AnimationContext.h"
|
||||
|
||||
#include "GotoPositionDlg.h"
|
||||
@@ -440,7 +439,6 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
ON_COMMAND(ID_CLEAR_REGISTRY, OnClearRegistryData)
|
||||
ON_COMMAND(ID_VALIDATELEVEL, OnValidatelevel)
|
||||
ON_COMMAND(ID_TOOLS_PREFERENCES, OnToolsPreferences)
|
||||
ON_COMMAND(ID_GRAPHICS_SETTINGS, OnGraphicsSettings)
|
||||
ON_COMMAND(ID_SWITCHCAMERA_DEFAULTCAMERA, OnSwitchToDefaultCamera)
|
||||
ON_COMMAND(ID_SWITCHCAMERA_SEQUENCECAMERA, OnSwitchToSequenceCamera)
|
||||
ON_COMMAND(ID_SWITCHCAMERA_SELECTEDCAMERA, OnSwitchToSelectedcamera)
|
||||
@@ -453,14 +451,6 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView)
|
||||
ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor)
|
||||
|
||||
ON_COMMAND_RANGE(ID_GAME_PC_ENABLELOWSPEC, ID_GAME_PC_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
|
||||
|
||||
ON_COMMAND_RANGE(ID_GAME_OSXMETAL_ENABLELOWSPEC, ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
|
||||
|
||||
ON_COMMAND_RANGE(ID_GAME_ANDROID_ENABLELOWSPEC, ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
|
||||
|
||||
ON_COMMAND_RANGE(ID_GAME_IOS_ENABLELOWSPEC, ID_GAME_IOS_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
|
||||
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
|
||||
ON_COMMAND_RANGE(ID_GAME_##CODENAME##_ENABLELOWSPEC, ID_GAME_##CODENAME##_ENABLEHIGHSPEC, OnChangeGameSpec)
|
||||
@@ -3674,13 +3664,6 @@ void CCryEditApp::OnToolsPreferences()
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnGraphicsSettings()
|
||||
{
|
||||
GraphicsSettingsDialog dlg(MainWindow::instance());
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnSwitchToDefaultCamera()
|
||||
{
|
||||
@@ -3815,91 +3798,6 @@ void CCryEditApp::OnOpenUICanvasEditor()
|
||||
QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable)
|
||||
{
|
||||
if (GetIEditor()->GetEditorConfigSpec() == spec && GetIEditor()->GetEditorConfigPlatform() == platform)
|
||||
{
|
||||
nCheck = 1;
|
||||
}
|
||||
enable = spec <= GetIEditor()->GetSystem()->GetMaxConfigSpec();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateGameSpec(QAction* action)
|
||||
{
|
||||
Q_ASSERT(action->isCheckable());
|
||||
int nCheck = 0;
|
||||
bool enable = true;
|
||||
switch (action->data().toInt())
|
||||
{
|
||||
case ID_GAME_PC_ENABLELOWSPEC:
|
||||
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_PC, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEMEDIUMSPEC:
|
||||
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_PC, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_PC, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_PC, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
|
||||
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_OSX_METAL, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
|
||||
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLELOWSPEC:
|
||||
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_ANDROID, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
|
||||
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLELOWSPEC:
|
||||
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_IOS, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
|
||||
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_IOS, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_IOS, nCheck, enable);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
|
||||
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_IOS, nCheck, enable);
|
||||
break;
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
|
||||
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
|
||||
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_##CODENAME, nCheck, enable);\
|
||||
break;\
|
||||
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
|
||||
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME, nCheck, enable);\
|
||||
break;\
|
||||
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
|
||||
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_##CODENAME, nCheck, enable);\
|
||||
break;
|
||||
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
|
||||
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
|
||||
#endif
|
||||
}
|
||||
action->setChecked(nCheck);
|
||||
action->setEnabled(enable);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
RecentFileList* CCryEditApp::GetRecentFileList()
|
||||
{
|
||||
|
||||
@@ -403,7 +403,6 @@ private:
|
||||
void OnClearRegistryData();
|
||||
void OnValidatelevel();
|
||||
void OnToolsPreferences();
|
||||
void OnGraphicsSettings();
|
||||
void OnSwitchToDefaultCamera();
|
||||
void OnUpdateSwitchToDefaultCamera(QAction* action);
|
||||
void OnSwitchToSequenceCamera();
|
||||
@@ -416,9 +415,6 @@ private:
|
||||
void OnOpenTrackView();
|
||||
void OnOpenAudioControlsEditor();
|
||||
void OnOpenUICanvasEditor();
|
||||
void OnChangeGameSpec(UINT nID);
|
||||
void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable);
|
||||
void OnUpdateGameSpec(QAction* action);
|
||||
void OnOpenQuickAccessBar();
|
||||
|
||||
public:
|
||||
|
||||
@@ -407,78 +407,6 @@ inline namespace Commands
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnChangeGameSpec(UINT nID)
|
||||
{
|
||||
switch (nID)
|
||||
{
|
||||
case ID_GAME_PC_ENABLELOWSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_PC);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEMEDIUMSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_PC);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_PC);
|
||||
break;
|
||||
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_PC);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_OSX_METAL);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL);
|
||||
break;
|
||||
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLELOWSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_ANDROID);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_ANDROID);
|
||||
break;
|
||||
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLELOWSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_IOS);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_IOS);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_IOS);
|
||||
break;
|
||||
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
|
||||
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_IOS);
|
||||
break;
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
|
||||
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
|
||||
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_##CODENAME);\
|
||||
break;\
|
||||
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
|
||||
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME);\
|
||||
break;\
|
||||
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
|
||||
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_##CODENAME);\
|
||||
break;
|
||||
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
|
||||
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
void CryEditPythonHandler::Reflect(AZ::ReflectContext* context)
|
||||
|
||||
@@ -458,25 +458,7 @@ void EditorViewportWidget::Update()
|
||||
SetFOV(cameraState.m_fovOrZoom);
|
||||
m_Camera.SetZRange(cameraState.m_nearClip, cameraState.m_farClip);
|
||||
}
|
||||
else if (!ed_useNewCameraSystem)
|
||||
{
|
||||
m_renderViewport->GetViewportContext()->SetCameraTransform(LYTransformToAZTransform(m_Camera.GetMatrix()));
|
||||
}
|
||||
|
||||
// Don't override the game mode FOV
|
||||
if (!GetIEditor()->IsInGameMode())
|
||||
{
|
||||
AZ::Matrix4x4 clipMatrix;
|
||||
AZ::MakePerspectiveFovMatrixRH(
|
||||
clipMatrix,
|
||||
GetFOV(),
|
||||
aznumeric_cast<float>(width()) / aznumeric_cast<float>(height()),
|
||||
m_Camera.GetNearPlane(),
|
||||
m_Camera.GetFarPlane(),
|
||||
true
|
||||
);
|
||||
m_renderViewport->GetViewportContext()->SetCameraProjectionMatrix(clipMatrix);
|
||||
}
|
||||
// Reset the camera update flag now that we're finished updating our viewport context
|
||||
m_updateCameraPositionNextTick = false;
|
||||
|
||||
@@ -632,7 +614,6 @@ void EditorViewportWidget::SetViewEntity(const AZ::EntityId& viewEntityId, bool
|
||||
void EditorViewportWidget::ResetToViewSourceType(const ViewSourceType& viewSourceType)
|
||||
{
|
||||
LockCameraMovement(true);
|
||||
m_pCameraFOVVariable = nullptr;
|
||||
m_viewEntityId.SetInvalid();
|
||||
m_cameraObjectId = GUID_NULL;
|
||||
m_viewSourceType = viewSourceType;
|
||||
@@ -2547,13 +2528,26 @@ void EditorViewportWidget::CenterOnSliceInstance()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void EditorViewportWidget::SetFOV(float fov)
|
||||
{
|
||||
if (m_pCameraFOVVariable)
|
||||
if (m_viewEntityId.IsValid())
|
||||
{
|
||||
m_pCameraFOVVariable->Set(fov);
|
||||
Camera::CameraRequestBus::Event(m_viewEntityId, &Camera::CameraComponentRequests::SetFov, AZ::RadToDeg(fov));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_camFOV = fov;
|
||||
// Set the active camera's FOV
|
||||
{
|
||||
AZ::Matrix4x4 clipMatrix;
|
||||
AZ::MakePerspectiveFovMatrixRH(
|
||||
clipMatrix,
|
||||
GetFOV(),
|
||||
aznumeric_cast<float>(width()) / aznumeric_cast<float>(height()),
|
||||
m_Camera.GetNearPlane(),
|
||||
m_Camera.GetFarPlane(),
|
||||
true
|
||||
);
|
||||
m_renderViewport->GetViewportContext()->SetCameraProjectionMatrix(clipMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewPane)
|
||||
@@ -2580,13 +2574,7 @@ float EditorViewportWidget::GetFOV() const
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pCameraFOVVariable)
|
||||
{
|
||||
float fov;
|
||||
m_pCameraFOVVariable->Get(fov);
|
||||
return fov;
|
||||
}
|
||||
else if (m_viewEntityId.IsValid())
|
||||
if (m_viewEntityId.IsValid())
|
||||
{
|
||||
float fov = AZ::RadToDeg(m_camFOV);
|
||||
Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFov);
|
||||
@@ -2970,7 +2958,12 @@ void EditorViewportWidget::RestoreViewportAfterGameMode()
|
||||
{
|
||||
Matrix34 preGameModeViewTM = m_preGameModeViewTM;
|
||||
|
||||
QString text = QString("You are exiting Game Mode. Would you like to restore the camera in the viewport to where it was before you entered Game Mode?<br/><br/><small>This option can always be changed in the General Preferences tab of the Editor Settings, by toggling the \"%1\" option.</small><br/><br/>").arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
|
||||
QString text =
|
||||
QString(
|
||||
tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you "
|
||||
"had entered Game mode.<br/><br/><small>If you dislike this setting you can always change this anytime in the global "
|
||||
"preferences.</small><br/><br/>"))
|
||||
.arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
|
||||
QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode");
|
||||
|
||||
// Read the popup disabled registry value
|
||||
@@ -2985,6 +2978,7 @@ void EditorViewportWidget::RestoreViewportAfterGameMode()
|
||||
messageBox.setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
QCheckBox* checkBox = new QCheckBox(QStringLiteral("Do not show this message again"));
|
||||
checkBox->setChecked(true);
|
||||
messageBox.setCheckBox(checkBox);
|
||||
|
||||
// Unconstrain the system cursor and make it visible before we show the dialog box, otherwise the user can't see the cursor.
|
||||
|
||||
@@ -506,7 +506,6 @@ protected:
|
||||
|
||||
CPredefinedAspectRatios m_predefinedAspectRatios;
|
||||
|
||||
IVariable* m_pCameraFOVVariable = nullptr;
|
||||
bool m_bCursorHidden = false;
|
||||
|
||||
void OnMenuResolutionCustom();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include <QTreeView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/SpinBox.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/any.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#endif
|
||||
|
||||
class QGridLayout;
|
||||
class QLabel;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class GraphicsSettingsDialog;
|
||||
}
|
||||
|
||||
// Description:
|
||||
// Status of cvar for a specifc platform and spec level
|
||||
// editedValue - current setting within Graphics Settings Dialog box
|
||||
// overwrittenValue - original setting from platform config file (set to originalValue if not found)
|
||||
// originalValue - original settings from sys_spec config file index
|
||||
|
||||
struct CVarFileStatus
|
||||
{
|
||||
AZStd::any editedValue;
|
||||
AZStd::any overwrittenValue;
|
||||
AZStd::any originalValue;
|
||||
CVarFileStatus(AZStd::any edit, AZStd::any over, AZStd::any orig) : editedValue(edit), overwrittenValue(over), originalValue(orig) {}
|
||||
};
|
||||
|
||||
// Description:
|
||||
// Status of specific cvar for Editor mapping
|
||||
// type - CVAR_INT / CVAR_FLOAT / CVAR_STRING
|
||||
// cvarGroup - source of cvar (sys_spec_particles, sys_spec_physics, etc.) or "miscellaneous" if only specified in platform config file
|
||||
// fileVals = CVarFileStatus for each spec level of a specific platform
|
||||
|
||||
struct CVarInfo
|
||||
{
|
||||
int type;
|
||||
AZStd::string cvarGroup;
|
||||
AZStd::vector<CVarFileStatus> fileVals;
|
||||
};
|
||||
|
||||
enum class GraphicsSettings
|
||||
{
|
||||
GameEffects,
|
||||
Light,
|
||||
ObjectDetail,
|
||||
Particles,
|
||||
Physics,
|
||||
PostProcessing,
|
||||
Quality,
|
||||
Shading,
|
||||
Shadows,
|
||||
Sound,
|
||||
Texture,
|
||||
TextureResolution,
|
||||
VolumetricEffects,
|
||||
Water,
|
||||
Miscellaneous,
|
||||
numSettings
|
||||
};
|
||||
|
||||
class GraphicsSettingsHeaderView;
|
||||
|
||||
class GraphicsSettingsTreeView
|
||||
: public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GraphicsSettingsTreeView(QWidget* parent = nullptr);
|
||||
|
||||
};
|
||||
|
||||
class GraphicsSettingsModel
|
||||
: public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphicsSettingsModel(QObject* parent = 0);
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
class GraphicsSettingsDialog
|
||||
: public QDialog,
|
||||
public ILoadConfigurationEntrySink
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit GraphicsSettingsDialog(QWidget* parent = nullptr);
|
||||
virtual ~GraphicsSettingsDialog();
|
||||
|
||||
bool IsCustom(void) { return m_showCustomSpec; }
|
||||
void UnloadCustomSpec(int specLevel);
|
||||
|
||||
// ILoadConfigurationEntrySink
|
||||
void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup) override;
|
||||
|
||||
public slots:
|
||||
//Accept and reject
|
||||
void reject() override;
|
||||
void accept() override;
|
||||
|
||||
private slots:
|
||||
//Update UIs
|
||||
void PlatformChanged(const QString& platform);
|
||||
bool CVarChanged(AZStd::any val, const char* cvarName, int specLevel);
|
||||
void CVarChanged(int i);
|
||||
void CVarChanged(double d);
|
||||
void CVarChanged(const QString& s);
|
||||
|
||||
private:
|
||||
|
||||
// The struct ParameterWidget is used to store the parameter widget
|
||||
// m_parameterName will be the name of the parameter the widget represent.
|
||||
struct ParameterWidget
|
||||
{
|
||||
ParameterWidget(QWidget* widget, QString parameterName = "");
|
||||
|
||||
QString GetToolTip() const;
|
||||
|
||||
const char* PARAMETER_TOOLTIP = "The variable will update render parameter \"%1\".";
|
||||
QWidget* m_widget;
|
||||
QString m_parameterName;
|
||||
};
|
||||
|
||||
struct CollapseGroup
|
||||
{
|
||||
QString m_groupName;
|
||||
QStandardItem* m_groupRow;
|
||||
QTreeView* m_treeView;
|
||||
bool m_isCollapsed;
|
||||
|
||||
CollapseGroup(QTreeView* treeView);
|
||||
|
||||
void ToggleCollapsed();
|
||||
};
|
||||
|
||||
void OpenCustomSpecDialog();
|
||||
void ApplyCustomSpec(const QString& customFilePath);
|
||||
bool IsCustomSpecAlreadyLoaded(const AZStd::string& filename) const;
|
||||
void SetSettingsTree(int numColumns);
|
||||
void SetCollapsed(const QModelIndex& index, bool flag);
|
||||
|
||||
enum CVarStateComparison
|
||||
{
|
||||
EDITED_OVERWRITTEN_COMPARE = 1,
|
||||
EDITED_ORIGINAL_COMPARE = 2,
|
||||
OVERWRITTEN_ORIGINAL_COMPARE = 3,
|
||||
|
||||
END_CVARSTATE_COMPARE,
|
||||
};
|
||||
|
||||
bool CheckCVarStatesForDiff(AZStd::pair<AZStd::string, CVarInfo>* it, int cfgFileIndex, CVarStateComparison cmp);
|
||||
|
||||
// Save out settings into project-level cfg files
|
||||
void SaveSystemSettings();
|
||||
|
||||
// Load in project-level cfg files for current platform
|
||||
void LoadPlatformConfigurations();
|
||||
// Build UI column for spec level of current platform
|
||||
void BuildColumn(int specLevel);
|
||||
// Initial UI building
|
||||
void BuildUI();
|
||||
// Cleaning out UI before loading new platform information
|
||||
void CleanUI();
|
||||
// Shows/hides custom spec option
|
||||
void ShowCustomSpecOption(bool show);
|
||||
// Shows/hides category labels and dropdowns
|
||||
void ShowCategories(bool show);
|
||||
// Warns about unsaved changes (returns true if accepted)
|
||||
bool SendUnsavedChangesWarning(bool cancel);
|
||||
|
||||
void LoadCVarGroupDirectory(const AZStd::string& path);
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// UI help functions
|
||||
|
||||
// Setup collapsed buttons
|
||||
void SetCollapsedLayout(const QString& groupName, QStandardItem* groupItem);
|
||||
// Sets the platform entry index for the given platform
|
||||
void SetPlatformEntry(ESystemConfigPlatform platform);
|
||||
// Gets the platform enum given the platform name
|
||||
ESystemConfigPlatform GetConfigPlatformFromName(const AZStd::string& platformName);
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Members
|
||||
|
||||
// Qt values
|
||||
const int INPUT_MIN_WIDTH = 100;
|
||||
const int INPUT_MIN_HEIGHT = 20;
|
||||
const int INPUT_ROW_SPAN = 1;
|
||||
const int INPUT_COLUMN_SPAN = 1;
|
||||
const int CVAR_ROW_OFFSET = 2;
|
||||
const int CVAR_VALUE_COLUMN_OFFSET = 1;
|
||||
const int PLATFORM_LABEL_ROW = 1;
|
||||
const int CVAR_LABEL_COLUMN = 1;
|
||||
|
||||
// Tool tips
|
||||
const QString SETTINGS_FILE_PATH = "Config/spec/";
|
||||
const char* CFG_FILEFILTER = "Cfg File(*.cfg);;All files(*)";
|
||||
|
||||
const int m_numSpecLevels = 4;
|
||||
|
||||
bool m_showCustomSpec;
|
||||
bool m_showCategories;
|
||||
GraphicsSettingsModel* m_graphicsSettingsModel;
|
||||
GraphicsSettingsHeaderView* m_headerView;
|
||||
int m_numColumns{ 0 };
|
||||
|
||||
const char* m_cvarGroupsFolder = "Config/CVarGroups";
|
||||
|
||||
QScopedPointer<Ui::GraphicsSettingsDialog> m_ui;
|
||||
|
||||
QVector<CollapseGroup*> m_uiCollapseGroup;
|
||||
|
||||
QVector<ParameterWidget*> m_parameterWidgets;
|
||||
|
||||
AZStd::string m_currentConfigFilename;
|
||||
size_t m_currentSpecIndex;
|
||||
|
||||
// cvar name --> pair(type, CVarStatus for each file)
|
||||
AZStd::unordered_map<AZStd::string, CVarInfo> m_cVarTracker;
|
||||
|
||||
AZStd::unordered_map<ESystemConfigPlatform, AZStd::vector<AZStd::string> > m_cfgFiles;
|
||||
|
||||
AZStd::vector<AZStd::pair<AZStd::string, ESystemConfigPlatform> > m_platformStrings;
|
||||
|
||||
struct CVarGroupInfo
|
||||
{
|
||||
QVector<QLabel*> m_platformLabels;
|
||||
QVector<QLabel*> m_cvarLabels;
|
||||
QVector<AzQtComponents::SpinBox*> m_cvarSpinBoxes;
|
||||
QVector<AzQtComponents::DoubleSpinBox*> m_cvarDoubleSpinBoxes;
|
||||
QVector<QLineEdit*> m_cvarLineEdits;
|
||||
QVector<QToolButton*> m_specFileArea;
|
||||
QVector<QWidget*> m_widgetInsertOrder;
|
||||
QStandardItem* m_treeRowItem;
|
||||
int m_currentRow;
|
||||
};
|
||||
|
||||
AZStd::unordered_map<AZStd::string, CVarGroupInfo> m_cvarGroupData;
|
||||
AZStd::vector<AZStd::string> m_cvarGroupOrder;
|
||||
|
||||
ESystemConfigPlatform m_currentPlatform;
|
||||
|
||||
int m_dirtyCVarCount;
|
||||
};
|
||||
|
||||
class GraphicsSettingsHeaderView
|
||||
: public QHeaderView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsSettingsHeaderView(GraphicsSettingsDialog* dialog, Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
bool event(QEvent* e) override;
|
||||
void mouseMoveEvent(QMouseEvent* e) override;
|
||||
void mouseReleaseEvent(QMouseEvent* e) override;
|
||||
|
||||
GraphicsSettingsDialog* m_dialog;
|
||||
int m_index{ -1 };
|
||||
};
|
||||
|
||||
|
||||
@@ -83,9 +83,9 @@ AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportC
|
||||
}
|
||||
|
||||
bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos)
|
||||
int dx, int dy)
|
||||
{
|
||||
if (previousMousePos == currentMousePos)
|
||||
if (dx == 0 && dy == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
|
||||
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
|
||||
{
|
||||
m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength();
|
||||
m_totalMouseMoveDelta += AZStd::abs(dx) + AZStd::abs(dy);
|
||||
}
|
||||
|
||||
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
|
||||
@@ -115,7 +115,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
Vec3 ydir = m.GetColumn1().GetNormalized();
|
||||
Vec3 pos = m.GetTranslation();
|
||||
|
||||
const float posDelta = 0.2f * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
|
||||
const float posDelta = 0.2f * dy * speedScale;
|
||||
pos = pos - ydir * posDelta;
|
||||
m_orbitDistance = m_orbitDistance + posDelta;
|
||||
m_orbitDistance = fabs(m_orbitDistance);
|
||||
@@ -126,7 +126,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
else if (m_inRotateMode)
|
||||
{
|
||||
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
|
||||
Ang3 angles(dy, 0, dx);
|
||||
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
|
||||
if (gSettings.invertYRotation)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
|
||||
Vec3 pos = m.GetTranslation();
|
||||
pos += 0.1f * xdir * (currentMousePos.m_x - previousMousePos.m_x) * speedScale + 0.1f * zdir * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
|
||||
pos += 0.1f * xdir * dx * speedScale + 0.1f * zdir * dy * speedScale;
|
||||
m.SetTranslation(pos);
|
||||
|
||||
AZ::Transform transform = viewportContext->GetCameraTransform();
|
||||
@@ -168,7 +168,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
|
||||
}
|
||||
else if (m_inOrbitMode)
|
||||
{
|
||||
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
|
||||
Ang3 angles(dy, 0, dx);
|
||||
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
|
||||
|
||||
if (gSettings.invertPan)
|
||||
@@ -302,20 +302,19 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
|
||||
bool shouldCaptureCursor = m_capturingCursor;
|
||||
bool shouldConsumeEvent = false;
|
||||
|
||||
if (id == AzFramework::InputDeviceMouse::SystemCursorPosition)
|
||||
if (id == AzFramework::InputDeviceMouse::Movement::X || id == AzFramework::InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
bool result = false;
|
||||
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
|
||||
GetViewportId(),
|
||||
[this, &result](AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequests* mouseRequests)
|
||||
{
|
||||
if (auto previousMousePosition = mouseRequests->PreviousViewportCursorScreenPosition();
|
||||
previousMousePosition.has_value())
|
||||
{
|
||||
result = HandleMouseMove(mouseRequests->ViewportCursorScreenPosition(), previousMousePosition.value());
|
||||
}
|
||||
});
|
||||
return result;
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
if (id == AzFramework::InputDeviceMouse::Movement::X)
|
||||
{
|
||||
dx = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
dy = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
|
||||
}
|
||||
return HandleMouseMove(dx, dy);
|
||||
}
|
||||
else if (id == MouseButton::Left)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace SandboxEditor
|
||||
|
||||
AZ::RPI::ViewportContextPtr GetViewportContext();
|
||||
|
||||
bool HandleMouseMove(const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos);
|
||||
bool HandleMouseMove(int dx, int dy);
|
||||
bool HandleMouseWheel(float zDelta);
|
||||
bool IsKeyDown(Qt::Key key) const;
|
||||
void UpdateCursorCapture(bool shouldCaptureCursor);
|
||||
|
||||
+13
-44
@@ -41,6 +41,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/Application/Ticker.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/EditorAnimationSystemRequestBus.h>
|
||||
#include <AzToolsFramework/SourceControl/QtSourceControlNotificationHandler.h>
|
||||
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
||||
@@ -93,6 +94,8 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "AssetEditor/AssetEditorWindow.h"
|
||||
#include "ActionManager.h"
|
||||
|
||||
#include <ImGuiBus.h>
|
||||
|
||||
using namespace AZ;
|
||||
using namespace AzQtComponents;
|
||||
using namespace AzToolsFramework;
|
||||
@@ -489,6 +492,16 @@ void MainWindow::Initialize()
|
||||
ActionOverrideRequestBus::Event(
|
||||
GetEntityContextId(), &ActionOverrideRequests::SetupActionOverrideHandler, this);
|
||||
|
||||
if (auto imGuiManager = AZ::Interface<ImGui::IImGuiManager>::Get())
|
||||
{
|
||||
auto handleImGuiStateChangeFn = [](bool enabled)
|
||||
{
|
||||
EditorWindowUIRequestBus::Broadcast(&EditorWindowUIRequests::SetEditorUiEnabled, enabled);
|
||||
};
|
||||
m_handleImGuiStateChangeHandler = ImGui::IImGuiManager::ImGuiSetEnabledEvent::Handler(handleImGuiStateChangeFn);
|
||||
imGuiManager->ConnectImGuiSetEnabledChangedHandler(m_handleImGuiStateChangeHandler);
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorEventsBus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, this);
|
||||
}
|
||||
|
||||
@@ -674,49 +687,6 @@ void MainWindow::InitActions()
|
||||
am->AddAction(ID_FILE_PROJECT_MANAGER_SETTINGS, tr("Edit Project Settings..."));
|
||||
am->AddAction(ID_FILE_PROJECT_MANAGER_NEW, tr("New Project..."));
|
||||
am->AddAction(ID_FILE_PROJECT_MANAGER_OPEN, tr("Open Project..."));
|
||||
am->AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_PC_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_PC_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_ANDROID_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_IOS_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
am->AddAction(ID_GAME_IOS_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#if defined(TOOLS_SUPPORT_JASPER)
|
||||
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, jasper)
|
||||
#endif
|
||||
#if defined(TOOLS_SUPPORT_PROVO)
|
||||
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, provo)
|
||||
#endif
|
||||
#if defined(TOOLS_SUPPORT_SALEM)
|
||||
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, salem)
|
||||
#endif
|
||||
#endif
|
||||
am->AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD, tr("Customize &Keyboard..."))
|
||||
.Connect(&QAction::triggered, this, &MainWindow::ShowKeyboardCustomization);
|
||||
am->AddAction(ID_TOOLS_EXPORT_SHORTCUTS, tr("&Export Keyboard Settings..."))
|
||||
@@ -724,7 +694,6 @@ void MainWindow::InitActions()
|
||||
am->AddAction(ID_TOOLS_IMPORT_SHORTCUTS, tr("&Import Keyboard Settings..."))
|
||||
.Connect(&QAction::triggered, this, &MainWindow::ImportKeyboardShortcuts);
|
||||
am->AddAction(ID_TOOLS_PREFERENCES, tr("Global Preferences..."));
|
||||
am->AddAction(ID_GRAPHICS_SETTINGS, tr("&Graphics Settings..."));
|
||||
|
||||
for (int i = ID_FILE_MRU_FIRST; i <= ID_FILE_MRU_LAST; ++i)
|
||||
{
|
||||
|
||||
@@ -249,6 +249,7 @@ private:
|
||||
|
||||
QPointer<ToolbarCustomizationDialog> m_toolbarCustomizationDialog;
|
||||
QScopedPointer<AzToolsFramework::QtSourceControlNotificationHandler> m_sourceControlNotifHandler;
|
||||
AZ::Event<bool>::Handler m_handleImGuiStateChangeHandler;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
static MainWindow* m_instance;
|
||||
|
||||
@@ -27,6 +27,7 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
Legacy::CryCommon
|
||||
|
||||
+2
@@ -66,3 +66,5 @@ namespace EntityOutliner
|
||||
emit OnOptionToggled(DisplayOption::AutoExpand, checked);
|
||||
}
|
||||
}
|
||||
|
||||
#include <UI/Outliner/moc_OutlinerDisplayOptionsMenu.cpp>
|
||||
|
||||
+18
-1
@@ -32,7 +32,24 @@ bool OutlinerSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelI
|
||||
|
||||
bool OutlinerSortFilterProxyModel::lessThan(const QModelIndex& leftIndex, const QModelIndex& rightIndex) const
|
||||
{
|
||||
return sourceModel()->data(leftIndex).toString() < sourceModel()->data(rightIndex).toString();
|
||||
if (leftIndex.isValid() && rightIndex.isValid())
|
||||
{
|
||||
QVariant leftData = sourceModel()->data(leftIndex);
|
||||
QVariant rightData = sourceModel()->data(rightIndex);
|
||||
|
||||
// make sure to compare the correct data types for sorting the current column
|
||||
AZ_Assert(leftData.type() == rightData.type(), "OutlinerSortFilterProxyModel::lessThan types do not agree!");
|
||||
if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::QString)
|
||||
{
|
||||
return leftData.toString() < rightData.toString();
|
||||
}
|
||||
else if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::ULongLong)
|
||||
{
|
||||
return leftData.toULongLong() < rightData.toULongLong();
|
||||
}
|
||||
AZ_Error("Editor", false, "Error! Unhandled type \"%s\" in OutlinerSortFilterProxyModel::lessThan", leftData.typeName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OutlinerSortFilterProxyModel::sort(int /*column*/, Qt::SortOrder /*order*/)
|
||||
|
||||
@@ -269,10 +269,12 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
OutlinerWidget::~OutlinerWidget()
|
||||
{
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
|
||||
@@ -1321,16 +1323,25 @@ static void SetEntityOutlinerState(Ui::OutlinerWidgetUI* entityOutlinerUi, const
|
||||
AzQtComponents::SetWidgetInteractEnabled(entityOutlinerUi->m_searchWidget, on);
|
||||
}
|
||||
|
||||
void OutlinerWidget::EnableUi(bool enable)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, enable);
|
||||
setEnabled(enable);
|
||||
}
|
||||
|
||||
void OutlinerWidget::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
EnableUi(enable);
|
||||
}
|
||||
|
||||
void OutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, false);
|
||||
setEnabled(false);
|
||||
EnableUi(false);
|
||||
}
|
||||
|
||||
void OutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
setEnabled(true);
|
||||
SetEntityOutlinerState(m_gui, true);
|
||||
EnableUi(true);
|
||||
}
|
||||
|
||||
void OutlinerWidget::OnSliceInstantiated(const AZ::Data::AssetId& /*sliceAssetId*/, AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& /*ticket*/)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -57,6 +58,7 @@ class OutlinerWidget
|
||||
, private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorEntityInfoNotificationBus::Handler
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -106,6 +108,9 @@ private:
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
|
||||
// EditorWindowUIRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
// Build a selection object from the given entities. Entities already in the Widget's selection buffers are ignored.
|
||||
template <class EntityIdCollection>
|
||||
QItemSelection BuildSelectionFromEntities(const EntityIdCollection& entityIds);
|
||||
@@ -171,6 +176,7 @@ private:
|
||||
AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index) const;
|
||||
QModelIndex GetIndexFromEntityId(const AZ::EntityId& entityId) const;
|
||||
void ExtractEntityIdsFromSelection(const QItemSelection& selection, AzToolsFramework::EntityIdList& entityIdList) const;
|
||||
void EnableUi(bool enable);
|
||||
|
||||
// AzToolsFramework::OutlinerModelNotificationBus::Handler
|
||||
// Receive notification from the outliner model that we should scroll
|
||||
|
||||
@@ -23,6 +23,7 @@ ly_add_target(
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorLib
|
||||
|
||||
@@ -17,19 +17,8 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// STL
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CRY Stuff ////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <ISystem.h>
|
||||
#include "Util/EditorUtils.h"
|
||||
#include "EditorCoreAPI.h"
|
||||
|
||||
@@ -31,6 +31,8 @@ ly_add_target(
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorLib
|
||||
|
||||
@@ -525,6 +525,7 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
|
||||
// view pane manager is interested when we enter/exit ComponentMode
|
||||
m_componentModeNotifications.BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
m_windowRequest.BusConnect();
|
||||
|
||||
m_componentModeNotifications.SetEnteredComponentModeFunc(
|
||||
[this](const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
@@ -545,10 +546,23 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
AzQtComponents::SetWidgetInteractEnabled(widget, on);
|
||||
});
|
||||
});
|
||||
|
||||
m_windowRequest.SetEnableEditorUiFunc(
|
||||
[this](bool enable)
|
||||
{
|
||||
// gray out panels when entering ImGui mode
|
||||
SetDefaultActionsEnabled(
|
||||
enable, m_registeredPanes,
|
||||
[](QWidget* widget, bool on)
|
||||
{
|
||||
AzQtComponents::SetWidgetInteractEnabled(widget, on);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QtViewPaneManager::~QtViewPaneManager()
|
||||
{
|
||||
m_windowRequest.BusDisconnect();
|
||||
m_componentModeNotifications.BusDisconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <AzQtComponents/Components/StyledDockWidget.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
@@ -249,8 +250,12 @@ private:
|
||||
QPointer<AzQtComponents::FancyDocking> m_advancedDockManager;
|
||||
|
||||
using EditorComponentModeNotificationBusImpl = AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBusImpl;
|
||||
EditorComponentModeNotificationBusImpl m_componentModeNotifications; /**< Helper for EditorComponentModeNotificationBus so
|
||||
* QtViewPaneManager does not need to inherit directly from it. */
|
||||
EditorComponentModeNotificationBusImpl m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
|
||||
using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl;
|
||||
EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
@@ -4083,7 +4083,12 @@ void CRenderViewport::RestoreViewportAfterGameMode()
|
||||
{
|
||||
Matrix34 preGameModeViewTM = m_preGameModeViewTM;
|
||||
|
||||
QString text = QString("You are exiting Game Mode. Would you like to restore the camera in the viewport to where it was before you entered Game Mode?<br/><br/><small>This option can always be changed in the General Preferences tab of the Editor Settings, by toggling the \"%1\" option.</small><br/><br/>").arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
|
||||
QString text =
|
||||
QString(
|
||||
tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you "
|
||||
"had entered Game mode.<br/><br/><small>If you dislike this setting you can always change this anytime in the global "
|
||||
"preferences.</small><br/><br/>"))
|
||||
.arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
|
||||
QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode");
|
||||
|
||||
// Read the popup disabled registry value
|
||||
@@ -4098,6 +4103,7 @@ void CRenderViewport::RestoreViewportAfterGameMode()
|
||||
messageBox.setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
QCheckBox* checkBox = new QCheckBox(QStringLiteral("Do not show this message again"));
|
||||
checkBox->setChecked(true);
|
||||
messageBox.setCheckBox(checkBox);
|
||||
|
||||
// Unconstrain the system cursor and make it visible before we show the dialog box, otherwise the user can't see the cursor.
|
||||
|
||||
@@ -187,7 +187,6 @@
|
||||
#define ID_SWITCHCAMERA_SEQUENCECAMERA 33701
|
||||
#define ID_SWITCHCAMERA_SELECTEDCAMERA 33702
|
||||
#define ID_TV_RECORD_AUTO 33703
|
||||
#define ID_GRAPHICS_SETTINGS 33705
|
||||
#define ID_VIEW_OPENVIEWPANE 33709
|
||||
#define ID_VIEW_OPENPANE_FIRST 33712
|
||||
#define ID_VIEW_OPENPANE_LAST 33811
|
||||
@@ -219,10 +218,6 @@
|
||||
#define ID_SPLINE_SNAP_GRID_X 33933
|
||||
#define ID_SPLINE_SNAP_GRID_Y 33934
|
||||
#define ID_FREEZE_TANGENTS 33935
|
||||
#define ID_GAME_PC_ENABLELOWSPEC 33960
|
||||
#define ID_GAME_PC_ENABLEMEDIUMSPEC 33961
|
||||
#define ID_GAME_PC_ENABLEHIGHSPEC 33962
|
||||
#define ID_GAME_PC_ENABLEVERYHIGHSPEC 33963
|
||||
#define ID_PANEL_VEG_CREATE_SEL 33990
|
||||
#define ID_TOOLS_UPDATEPROCEDURALVEGETATION 33999
|
||||
#define ID_DISPLAY_GOTOPOSITION 34004
|
||||
@@ -287,14 +282,6 @@
|
||||
#define ID_CLEAR_REGISTRY 34470
|
||||
#define ID_SOUND_STOPALLSOUNDS 34476
|
||||
#define ID_AUDIO_REFRESH_AUDIO_SYSTEM 34477
|
||||
#define ID_GAME_ANDROID_ENABLELOWSPEC 34490
|
||||
#define ID_GAME_ANDROID_ENABLEMEDIUMSPEC 34491
|
||||
#define ID_GAME_ANDROID_ENABLEHIGHSPEC 34492
|
||||
#define ID_GAME_ANDROID_ENABLEVERYHIGHSPEC 34493
|
||||
#define ID_GAME_IOS_ENABLELOWSPEC 34494
|
||||
#define ID_GAME_IOS_ENABLEMEDIUMSPEC 34495
|
||||
#define ID_GAME_IOS_ENABLEHIGHSPEC 34496
|
||||
#define ID_GAME_IOS_ENABLEVERYHIGHSPEC 34497
|
||||
#define ID_OPEN_AUDIO_CONTROLS_BROWSER 34580
|
||||
#define ID_CREATE_GLOBAL_FG_MODULE_FROM_SELECTION 35076
|
||||
#define ID_CREATE_LEVEL_FG_MODULE_FROM_SELECTION 35077
|
||||
@@ -324,19 +311,6 @@
|
||||
#define ID_DOCUMENTATION_FEEDBACK 36043
|
||||
#define ID_OPEN_SUBSTANCE_EDITOR 36060
|
||||
#define ID_IMPORT_ASSET 36069
|
||||
#define ID_GAME_PROVO_ENABLELOWSPEC 34603
|
||||
#define ID_GAME_PROVO_ENABLEMEDIUMSPEC 34604
|
||||
#define ID_GAME_PROVO_ENABLEHIGHSPEC 34605
|
||||
#define ID_GAME_OSXMETAL_ENABLELOWSPEC 34606
|
||||
#define ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC 34607
|
||||
#define ID_GAME_OSXMETAL_ENABLEHIGHSPEC 34608
|
||||
#define ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC 34609
|
||||
#define ID_GAME_SALEM_ENABLELOWSPEC 34610
|
||||
#define ID_GAME_SALEM_ENABLEMEDIUMSPEC 34611
|
||||
#define ID_GAME_SALEM_ENABLEHIGHSPEC 34612
|
||||
#define ID_GAME_JASPER_ENABLELOWSPEC 34613
|
||||
#define ID_GAME_JASPER_ENABLEMEDIUMSPEC 34614
|
||||
#define ID_GAME_JASPER_ENABLEHIGHSPEC 34615
|
||||
#define ID_FILE_RESAVESLICES 36210
|
||||
#define FIRST_QT_ACTION 50000
|
||||
#define ID_VIEW_CONSOLEWINDOW 50001
|
||||
|
||||
@@ -1,25 +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
|
||||
*
|
||||
*/
|
||||
|
||||
#GraphicsSettingsDialog QHeaderView::section
|
||||
{
|
||||
background: #2D2D2D;
|
||||
}
|
||||
|
||||
#GraphicsSettingsDialog QHeaderView::down-arrow
|
||||
{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
image: url(:/Gallery/Delete.svg);
|
||||
}
|
||||
|
||||
#GraphicsSettingsDialog QHeaderView::up-arrow
|
||||
{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
image: url(:/Gallery/Delete.svg);
|
||||
}
|
||||
@@ -3,6 +3,5 @@
|
||||
<file alias="Assets/Editor/Style/Editor.qss">Editor.qss</file>
|
||||
<file alias="Assets/Editor/Style/EditorPreferencesDialog.qss">EditorPreferencesDialog.qss</file>
|
||||
<file alias="Assets/Editor/Style/LayoutConfigDialog.qss">LayoutConfigDialog.qss</file>
|
||||
<file alias="Assets/Editor/Style/GraphicsSettingsDialog.qss">GraphicsSettingsDialog.qss</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
#include "CryEdit.h"
|
||||
#include "LevelFileDialog.h"
|
||||
|
||||
// NewsShared
|
||||
#include <NewsShared/ResourceManagement/ResourceManifest.h> // for News::ResourceManifest
|
||||
#include <NewsShared/Qt/ArticleViewContainer.h> // for News::ArticleViewContainer
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <WelcomeScreen/ui_WelcomeScreenDialog.h>
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include "NewsShared/LogType.h"
|
||||
#include "NewsShared/ErrorCodes.h"
|
||||
#endif
|
||||
|
||||
namespace News {
|
||||
@@ -62,9 +60,6 @@ private:
|
||||
void OnRecentLevelTableItemClicked(const QModelIndex& index);
|
||||
void OnCloseBtnClicked(bool checked);
|
||||
|
||||
void SyncFail(News::ErrorCode error);
|
||||
void SyncSuccess();
|
||||
|
||||
private Q_SLOTS:
|
||||
void previewAreaScrolled();
|
||||
};
|
||||
|
||||
@@ -583,9 +583,6 @@ set(FILES
|
||||
SettingsManager.h
|
||||
SettingsManagerDialog.h
|
||||
SettingsManagerDialog.ui
|
||||
GraphicsSettingsDialog.h
|
||||
GraphicsSettingsDialog.cpp
|
||||
graphicssettingsdialog.ui
|
||||
AboutDialog.cpp
|
||||
ErrorReportTableModel.h
|
||||
ErrorReportTableModel.cpp
|
||||
|
||||
@@ -1,270 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GraphicsSettingsDialog</class>
|
||||
<widget class="QDialog" name="GraphicsSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1292</width>
|
||||
<height>565</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Graphics Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="m_generalLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="3">
|
||||
<widget class="QWidget" name="m_platform" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_platformEntry"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="m_selectCustomSpecButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Resource</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="m_platformLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Platform</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Line" name="m_lineSpacer">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="m_scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="m_scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1272</width>
|
||||
<height>452</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="GraphicsSettingsTreeView" name="m_graphicsSettingsTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="m_horizontalLayout">
|
||||
<item>
|
||||
<spacer name="m_horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_applyButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(233, 118, 17);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_cancelButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>line</zorder>
|
||||
<zorder>m_scrollArea</zorder>
|
||||
<zorder>line_2</zorder>
|
||||
<zorder>widget</zorder>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>GraphicsSettingsTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>GraphicsSettingsDialog.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>m_cancelButton</tabstop>
|
||||
<tabstop>m_applyButton</tabstop>
|
||||
<tabstop>m_scrollArea</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -27,11 +27,17 @@ namespace AZ
|
||||
template <typename... Params>
|
||||
EventHandler<Params...>::EventHandler(const EventHandler& rhs)
|
||||
: m_callback(rhs.m_callback)
|
||||
, m_event(rhs.m_event)
|
||||
{
|
||||
// Copy the callback function, then perform a Connect with the new event
|
||||
if (rhs.m_event)
|
||||
// Copy the callback and event, then perform a Connect to the event
|
||||
if (m_callback && m_event)
|
||||
{
|
||||
rhs.m_event->Connect(*this);
|
||||
m_event->Connect(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It was not possible to connect to the event, set it to nullptr
|
||||
m_event = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +71,16 @@ namespace AZ
|
||||
{
|
||||
Disconnect();
|
||||
m_callback = rhs.m_callback;
|
||||
if (rhs.m_event)
|
||||
m_event = rhs.m_event;
|
||||
// Copy the callback and event, then perform a Connect to the event
|
||||
if (m_callback && m_event)
|
||||
{
|
||||
rhs.m_event->Connect(*this);
|
||||
m_event->Connect(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It was not possible to connect to the event, set it to nullptr
|
||||
m_event = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
JsonUuidSerializer::JsonUuidSerializer()
|
||||
: m_zeroUuidString(AZ::Uuid::CreateNull().ToString<AZStd::string>())
|
||||
, m_zeroUuidStringNoDashes(AZ::Uuid::CreateNull().ToString<AZStd::string>(true, false))
|
||||
{
|
||||
m_uuidFormat = AZStd::regex(R"(\{[a-f0-9]{8}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[a-f0-9]{12}\})",
|
||||
AZStd::regex_constants::icase | AZStd::regex_constants::optimize);
|
||||
@@ -53,7 +55,7 @@ namespace AZ
|
||||
|
||||
Uuid* valAsUuid = reinterpret_cast<Uuid*>(outputValue);
|
||||
|
||||
if (IsExplicitDefault(inputValue))
|
||||
if (IsExplicitDefault(inputValue) || (inputValue == m_zeroUuidString.c_str()) || (inputValue == m_zeroUuidStringNoDashes.c_str()))
|
||||
{
|
||||
*valAsUuid = AZ::Uuid::CreateNull();
|
||||
return MessageResult("Uuid value set to default of null.", JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed));
|
||||
|
||||
@@ -47,6 +47,8 @@ namespace AZ
|
||||
const Uuid& valueTypeId, JsonSerializerContext& context);
|
||||
|
||||
private:
|
||||
const AZStd::string m_zeroUuidString;
|
||||
const AZStd::string m_zeroUuidStringNoDashes;
|
||||
AZStd::regex m_uuidFormat;
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
@@ -3252,6 +3252,7 @@ LUA_API const Node* lua_getDummyNode()
|
||||
else if (Internal::LuaScriptNumber<short>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<AZ::s64>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<long>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<AZ::s8>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<unsigned char>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<unsigned short>::FromStack(param, result)) return result;
|
||||
else if (Internal::LuaScriptNumber<unsigned int>::FromStack(param, result)) return result;
|
||||
|
||||
@@ -32,6 +32,15 @@ namespace AZ
|
||||
{
|
||||
if (m_hashes.size() < m_hashes.max_size())
|
||||
{
|
||||
constexpr size_t MaxTagSize = TagName{}.max_size();
|
||||
if (specialization.size() > MaxTagSize)
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Cannot append Specialization tag of "%.*s.")"
|
||||
" It is longer than the MaxTagNameSize of %zu", AZ_STRING_ARG(specialization),
|
||||
MaxTagSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_names.push_back(TagName{ specialization });
|
||||
TagName& tag = m_names.back();
|
||||
AZStd::to_lower(tag.begin(), tag.end());
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace AZ
|
||||
class Specializations
|
||||
{
|
||||
public:
|
||||
static constexpr size_t MaxTagNameSize = 32;
|
||||
static constexpr size_t MaxTagNameSize = 64;
|
||||
static constexpr size_t MaxCount = 15;
|
||||
static constexpr size_t NotFound = static_cast<size_t>(-1);
|
||||
using TagName = AZStd::fixed_string<MaxTagNameSize>;
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace AZ {
|
||||
AZStd::mutex g_dbgLoadingMutex;
|
||||
HANDLE g_currentProcess = 0; /// We deal with only one process for now.
|
||||
CRITICAL_SECTION g_csDbgHelpDll; /// All dbg help functions are single threaded, so we need to control the access.
|
||||
AZStd::fixed_vector<SymbolStorage::ModuleInfo, 256> g_moduleInfo;
|
||||
AZStd::fixed_vector<SymbolStorage::ModuleInfo, 2048> g_moduleInfo;
|
||||
|
||||
// reserve 4k of scratch space so that we can get some callstack information without any allocations and as little stack frame usage as possible.
|
||||
const size_t g_scratchSpaceSize = 2048;
|
||||
|
||||
@@ -257,6 +257,48 @@ namespace UnitTest
|
||||
EXPECT_FALSE(testEvent1.HasHandlerConnected());
|
||||
EXPECT_TRUE(testEvent2.HasHandlerConnected());
|
||||
}
|
||||
|
||||
TEST_F(EventTests, TestHandlerCopyConstructorOperator)
|
||||
{
|
||||
int32_t invokedCounter = 0;
|
||||
|
||||
AZ::Event<> testEvent;
|
||||
AZ::Event<>::Handler testHandler([&invokedCounter]() { invokedCounter++; });
|
||||
|
||||
testHandler.Connect(testEvent);
|
||||
|
||||
AZ::Event<>::Handler testHandler2(testHandler);
|
||||
|
||||
EXPECT_TRUE(testHandler.IsConnected());
|
||||
EXPECT_TRUE(testHandler2.IsConnected());
|
||||
|
||||
EXPECT_TRUE(invokedCounter == 0);
|
||||
testEvent.Signal();
|
||||
EXPECT_TRUE(invokedCounter == 2);
|
||||
}
|
||||
|
||||
TEST_F(EventTests, TestHandlerCopyAssignmentOperator)
|
||||
{
|
||||
int32_t invokedCounter = 0;
|
||||
|
||||
AZ::Event<> testEvent;
|
||||
AZ::Event<>::Handler testHandler([&invokedCounter]() { invokedCounter++; });
|
||||
|
||||
testHandler.Connect(testEvent);
|
||||
|
||||
AZ::Event<>::Handler testHandler2;
|
||||
|
||||
EXPECT_TRUE(testHandler.IsConnected());
|
||||
EXPECT_FALSE(testHandler2.IsConnected());
|
||||
|
||||
testHandler2 = testHandler;
|
||||
|
||||
EXPECT_TRUE(testHandler2.IsConnected());
|
||||
|
||||
EXPECT_TRUE(invokedCounter == 0);
|
||||
testEvent.Signal();
|
||||
EXPECT_TRUE(invokedCounter == 2);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationSettings.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <Tests/Serialization/Json/JsonSerializationTests.h>
|
||||
|
||||
@@ -43,7 +44,9 @@ namespace JsonSerializationTests
|
||||
}
|
||||
|
||||
void CheckApplyPatchOutcome(const char* target, const char* patch,
|
||||
AZ::JsonSerializationResult::Outcomes outcome, AZ::JsonSerializationResult::Processing processing)
|
||||
AZ::JsonSerializationResult::Outcomes outcome,
|
||||
AZ::JsonSerializationResult::Processing processing,
|
||||
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
|
||||
{
|
||||
m_jsonDocument->Parse(target);
|
||||
ASSERT_FALSE(m_jsonDocument->HasParseError());
|
||||
@@ -53,12 +56,24 @@ namespace JsonSerializationTests
|
||||
ASSERT_FALSE(patchDocument.HasParseError());
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(*m_jsonDocument,
|
||||
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch);
|
||||
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch, settings);
|
||||
EXPECT_EQ(result.GetTask(), AZ::JsonSerializationResult::Tasks::Merge);
|
||||
EXPECT_EQ(result.GetOutcome(), outcome);
|
||||
EXPECT_EQ(result.GetProcessing(), processing);
|
||||
}
|
||||
|
||||
void CheckApplyPatchOutcome(
|
||||
const char* target,
|
||||
const char* patch,
|
||||
const char* expectedPatchedResult,
|
||||
AZ::JsonSerializationResult::Outcomes outcome,
|
||||
AZ::JsonSerializationResult::Processing processing,
|
||||
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
|
||||
{
|
||||
CheckApplyPatchOutcome(target, patch, outcome, processing, settings);
|
||||
Expect_DocStrEq(expectedPatchedResult);
|
||||
}
|
||||
|
||||
void CheckCreatePatch_Core(const char* source, AZStd::string_view patch, const char* target,
|
||||
AZ::JsonMergeApproach approach)
|
||||
{
|
||||
@@ -262,6 +277,36 @@ namespace JsonSerializationTests
|
||||
Outcomes::TypeMismatch, Processing::Halted);
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchWithCustomReportingCallback_ReportPartialSkip)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
if (result.GetProcessing() == Processing::Halted)
|
||||
{
|
||||
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
AZ::JsonApplyPatchSettings applyPatchSettings;
|
||||
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
CheckApplyPatchOutcome(
|
||||
R"({})",
|
||||
R"([
|
||||
{ "op": "add", "path": "/nonexistent_key/new_member", "value": "someValue" },
|
||||
{ "op": "add", "path": "/test", "value": "someValue" }
|
||||
])",
|
||||
R"(
|
||||
{ "test": "someValue" }
|
||||
)",
|
||||
Outcomes::PartialSkip,
|
||||
Processing::Completed,
|
||||
AZStd::move(applyPatchSettings));
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchAddUnnamedMember_ReportsSuccess)
|
||||
{
|
||||
CheckApplyPatch(
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Physics
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<CharacterConfiguration, AzPhysics::SimulatedBodyConfiguration>()
|
||||
->Version(2)
|
||||
->Version(3)
|
||||
->Field("CollisionLayer", &CharacterConfiguration::m_collisionLayer)
|
||||
->Field("CollisionGroupId", &CharacterConfiguration::m_collisionGroupId)
|
||||
->Field("Material", &CharacterConfiguration::m_materialSelection)
|
||||
@@ -94,6 +94,7 @@ namespace Physics
|
||||
->Field("MinDistance", &CharacterConfiguration::m_minimumMovementDistance)
|
||||
->Field("MaxSpeed", &CharacterConfiguration::m_maximumSpeed)
|
||||
->Field("ColliderTag", &CharacterConfiguration::m_colliderTag)
|
||||
->Field("ApplyMoveOnPhysicsTick", &CharacterConfiguration::m_applyMoveOnPhysicsTick)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
@@ -127,6 +128,9 @@ namespace Physics
|
||||
->Attribute(AZ::Edit::Attributes::Step, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CharacterConfiguration::m_colliderTag,
|
||||
"Collider Tag", "Used to identify the collider associated with the character controller")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CharacterConfiguration::m_applyMoveOnPhysicsTick,
|
||||
"Apply Move On Tick", "Requests to add velocity will be accumulated and applied once on the physics pre-simulation tick "
|
||||
"If unticked, explicit call to apply requested velocity is required")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace Physics
|
||||
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig; //!< The shape to use when creating the character controller.
|
||||
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
|
||||
bool m_applyMoveOnPhysicsTick = true; //!< Should accumulated velocity be applied on the physics tick.
|
||||
};
|
||||
|
||||
/// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace AzPhysics
|
||||
->Property("Distance", BehaviorValueProperty(&RayCastRequest::m_distance))
|
||||
->Property("Start", BehaviorValueProperty(&RayCastRequest::m_start))
|
||||
->Property("Direction", BehaviorValueProperty(&RayCastRequest::m_direction))
|
||||
->Property("ReportMultipleHits", BehaviorValueProperty(&RayCastRequest::m_reportMultipleHits))
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +154,45 @@ namespace AzPhysics
|
||||
->Field("ReportMultipleHits", &ShapeCastRequest::m_reportMultipleHits)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<ShapeCastRequest>("ShapeCastRequest")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Distance", BehaviorValueProperty(&ShapeCastRequest::m_distance))
|
||||
->Property("Start", BehaviorValueProperty(&ShapeCastRequest::m_start))
|
||||
->Property("Direction", BehaviorValueProperty(&ShapeCastRequest::m_direction))
|
||||
;
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateSphereCastRequest",
|
||||
[](float radius, const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType, CollisionGroup collisionGroup)
|
||||
{
|
||||
return ShapeCastRequestHelpers::CreateSphereCastRequest(
|
||||
radius, startPose, direction, distance, queryType, collisionGroup, nullptr);
|
||||
});
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateBoxCastRequest",
|
||||
[](const AZ::Vector3& boxDimensions, const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType, CollisionGroup collisionGroup)
|
||||
{
|
||||
return ShapeCastRequestHelpers::CreateBoxCastRequest(
|
||||
boxDimensions, startPose, direction, distance, queryType, collisionGroup, nullptr);
|
||||
});
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateCapsuleCastRequest",
|
||||
[](float capsuleRadius, float capsuleHeight, const AZ::Transform& startPose, const AZ::Vector3& direction, float distance,
|
||||
SceneQuery::QueryType queryType, CollisionGroup collisionGroup)
|
||||
{
|
||||
return ShapeCastRequestHelpers::CreateCapsuleCastRequest(
|
||||
capsuleRadius, capsuleHeight, startPose, direction, distance, queryType, collisionGroup, nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShapeCastRequestHelpers
|
||||
@@ -219,6 +259,40 @@ namespace AzPhysics
|
||||
->Field("ShapeConfiguration", &OverlapRequest::m_shapeConfiguration)
|
||||
;
|
||||
}
|
||||
|
||||
if (auto* behaviorContext = azdynamic_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<OverlapRequest>("OverlapRequest")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
->Property("Pose", BehaviorValueProperty(&OverlapRequest::m_pose))
|
||||
;
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateSphereOverlapRequest",
|
||||
[](float radius, const AZ::Transform& pose)
|
||||
{
|
||||
return OverlapRequestHelpers::CreateSphereOverlapRequest(
|
||||
radius, pose, nullptr);
|
||||
});
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateBoxOverlapRequest",
|
||||
[](const AZ::Vector3& boxDimensions, const AZ::Transform& pose)
|
||||
{
|
||||
return OverlapRequestHelpers::CreateBoxOverlapRequest(
|
||||
boxDimensions, pose, nullptr);
|
||||
});
|
||||
|
||||
behaviorContext->Method(
|
||||
"CreateCapsuleOverlapRequest",
|
||||
[](float height, float radius, const AZ::Transform& pose)
|
||||
{
|
||||
return OverlapRequestHelpers::CreateCapsuleOverlapRequest(
|
||||
height, radius, pose, nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace OverlapRequestHelpers
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace AzPhysics
|
||||
->Attribute(AZ::Script::Attributes::Category, "Physics")
|
||||
->Method("GetOnGravityChangeEvent", getOnGravityChange)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, gravityChangedEventDescription)
|
||||
->Method("QueryScene", &Scene::QueryScene)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AzPhysics
|
||||
{"Tick time"} // Parameters
|
||||
};
|
||||
|
||||
behaviorContext->Class<SystemInterface>("System Interface")
|
||||
behaviorContext->Class<SystemInterface>("PhysicsSystemInterface")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "physics")
|
||||
->Attribute(AZ::Script::Attributes::Category, "PhysX")
|
||||
@@ -49,7 +49,21 @@ namespace AzPhysics
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, presimulateEventDescription)
|
||||
->Method("GetOnPostsimulateEvent", getOnPostsimulateEvent)
|
||||
->Attribute(AZ::Script::Attributes::AzEventDescription, postsimulateEventDescription)
|
||||
;
|
||||
->Method("GetSceneHandle", &SystemInterface::GetSceneHandle)
|
||||
->Method("GetScene", &SystemInterface::GetScene);
|
||||
|
||||
behaviorContext->Method(
|
||||
"GetPhysicsSystem",
|
||||
[]()
|
||||
{
|
||||
return AZ::Interface<AzPhysics::SystemInterface>::Get();
|
||||
});
|
||||
|
||||
behaviorContext
|
||||
->Constant("DefaultPhysicsSceneName", BehaviorConstant(DefaultPhysicsSceneName))
|
||||
->Constant("DefaultPhysicsSceneId", BehaviorConstant(DefaultPhysicsSceneId))
|
||||
->Constant("EditorPhysicsSceneName", BehaviorConstant(EditorPhysicsSceneName))
|
||||
->Constant("EditorPhysicsSceneId", BehaviorConstant(EditorPhysicsSceneId));
|
||||
}
|
||||
}
|
||||
} // namespace AzPhysics
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace AzFramework
|
||||
|
||||
//! This is called when the window is deactivated from code or if the user closes the window.
|
||||
virtual void OnWindowClosed() {};
|
||||
|
||||
//! This is called when vsync interval is changed.
|
||||
virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); };
|
||||
};
|
||||
using WindowNotificationBus = AZ::EBus<WindowNotifications>;
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_ERRNO_T_TYPEDEF 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_POSIX_LOCALTIME_R 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL "python.sh"
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PROCESSLAUNCH_DEFAULT 0
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_ERRNO_T_TYPEDEF 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_POSIX_LOCALTIME_R 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL "python.sh"
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PROCESSLAUNCH_DEFAULT 0
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace AzNetworking
|
||||
|
||||
void TcpSocketManager::ProcessEvents(AZ::TimeMs maxBlockMs, const SocketEventCallback& readCallback, const SocketEventCallback& writeCallback)
|
||||
{
|
||||
if(static_cast<int32_t>(m_maxFd) <= 0 && m_socketFds.empty())
|
||||
if(static_cast<int32_t>(m_maxFd) <= 0 || m_socketFds.empty())
|
||||
{
|
||||
// There are no available sockets to process
|
||||
return;
|
||||
|
||||
@@ -36,8 +36,47 @@ namespace AzToolsFramework
|
||||
/// Retrieve the main application window.
|
||||
virtual QWidget* GetAppMainWindow() { return nullptr; }
|
||||
};
|
||||
|
||||
using EditorWindowRequestBus = AZ::EBus<EditorWindowRequests>;
|
||||
|
||||
class EditorWindowUIRequests : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
using Bus = AZ::EBus<EditorWindowUIRequests>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Enable/Disable the Editor UI.
|
||||
virtual void SetEditorUiEnabled([[maybe_unused]] bool enable) {}
|
||||
};
|
||||
using EditorWindowUIRequestBus = AZ::EBus<EditorWindowUIRequests>;
|
||||
|
||||
using EnableUiFunction = AZStd::function<void(bool)>;
|
||||
|
||||
/// Helper for EditorWindowRequests to be used as a
|
||||
/// member instead of inheriting from EBus directly.
|
||||
class EditorWindowRequestBusImpl
|
||||
: public EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
/// Set the function to be called when entering ImGui Mode.
|
||||
void SetEnableEditorUiFunc(const EnableUiFunction enableEditorUiFunc)
|
||||
{
|
||||
m_enableEditorUiFunc = AZStd::move(enableEditorUiFunc);
|
||||
}
|
||||
|
||||
private:
|
||||
// EditorWindowRequestBus
|
||||
void SetEditorUiEnabled( [[maybe_unused]] bool enable) override
|
||||
{
|
||||
m_enableEditorUiFunc(enable);
|
||||
}
|
||||
|
||||
EnableUiFunction m_enableEditorUiFunc; ///< Function to call when entering ImGui Mode.
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
#endif // AZTOOLSFRAMEWORK_EDITORWINDOWREQUESTBUS_H
|
||||
|
||||
+21
-12
@@ -597,22 +597,23 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (m_rootInstance && m_playInEditorData.m_isEnabled)
|
||||
{
|
||||
auto end = m_playInEditorData.m_deactivatedEntities.rend();
|
||||
for (auto it = m_playInEditorData.m_deactivatedEntities.rbegin(); it != end; ++it)
|
||||
{
|
||||
AZ_Assert(*it, "Invalid entity added to list for re-activation after play-in-editor stopped.");
|
||||
(*it)->Activate();
|
||||
}
|
||||
m_playInEditorData.m_deactivatedEntities.clear();
|
||||
|
||||
AZ_Assert(m_playInEditorData.m_entities.IsSet(),
|
||||
"Invalid Game Mode Entities Container encountered after play-in-editor stopped. "
|
||||
"Confirm that the container was initialized correctly");
|
||||
|
||||
m_playInEditorData.m_entities.DespawnAllEntities();
|
||||
m_playInEditorData.m_entities.Alert(
|
||||
[assets = AZStd::move(m_playInEditorData.m_assets)]([[maybe_unused]]uint32_t generation) mutable
|
||||
[assets = AZStd::move(m_playInEditorData.m_assets),
|
||||
deactivatedEntities = AZStd::move(m_playInEditorData.m_deactivatedEntities)]
|
||||
([[maybe_unused]]uint32_t generation) mutable
|
||||
{
|
||||
auto end = deactivatedEntities.rend();
|
||||
for (auto it = deactivatedEntities.rbegin(); it != end; ++it)
|
||||
{
|
||||
AZ_Assert(*it, "Invalid entity added to list for re-activation after play-in-editor stopped.");
|
||||
(*it)->Activate();
|
||||
}
|
||||
|
||||
for (auto& asset : assets)
|
||||
{
|
||||
if (asset)
|
||||
@@ -624,13 +625,21 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
AZ::ScriptSystemRequestBus::Broadcast(&AZ::ScriptSystemRequests::GarbageCollect);
|
||||
|
||||
// This is a workaround until the replacement for GameEntityContext is done
|
||||
AzFramework::GameEntityContextEventBus::Broadcast(&AzFramework::GameEntityContextEventBus::Events::OnGameEntitiesReset);
|
||||
});
|
||||
m_playInEditorData.m_entities.Clear();
|
||||
|
||||
// This is a workaround until the replacement for GameEntityContext is done
|
||||
AzFramework::GameEntityContextEventBus::Broadcast(&AzFramework::GameEntityContextEventBus::Events::OnGameEntitiesReset);
|
||||
}
|
||||
|
||||
// Game entity cleanup is queued onto the next tick via the DespawnEntities call.
|
||||
// To avoid both game entities and Editor entities active at the same time
|
||||
// we flush the tick queue to ensure the game entities are cleared first.
|
||||
// The Alert callback that follows the DespawnEntities call will then reactivate the editor entities
|
||||
// This should be considered temporary as a move to a less rigid event sequence that supports async entity clean up
|
||||
// is the desired direction forward.
|
||||
AZ::TickBus::ExecuteQueuedEvents();
|
||||
|
||||
m_playInEditorData.m_isEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <AzFramework/Input/Buses/Notifications/InputChannelNotificationBus.h>
|
||||
#include <AzFramework/Input/Buses/Requests/InputChannelRequestBus.h>
|
||||
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCursor>
|
||||
@@ -187,12 +188,6 @@ namespace AzToolsFramework
|
||||
|
||||
bool QtEventToAzInputMapper::HandlesInputEvent(const AzFramework::InputChannel& channel) const
|
||||
{
|
||||
const AzFramework::InputChannelId& channelId = channel.GetInputChannelId();
|
||||
if (channelId == AzFramework::InputDeviceMouse::Movement::X || channelId == AzFramework::InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We map keyboard and mouse events from Qt, so flag all events coming from those devices
|
||||
// as handled by our synthetic event system.
|
||||
const AzFramework::InputDeviceId& deviceId = channel.GetInputDevice().GetInputDeviceId();
|
||||
@@ -210,6 +205,22 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::SetCursorCaptureEnabled(bool enabled)
|
||||
{
|
||||
if (m_capturingCursor != enabled)
|
||||
{
|
||||
m_capturingCursor = enabled;
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
qApp->setOverrideCursor(Qt::BlankCursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
qApp->restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QtEventToAzInputMapper::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
// Abort if processing isn't enabled.
|
||||
@@ -284,13 +295,25 @@ namespace AzToolsFramework
|
||||
{
|
||||
auto systemCursorChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::SystemCursorPosition);
|
||||
auto movementXChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::X);
|
||||
auto movementYChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Y);
|
||||
auto mouseWheelChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Z);
|
||||
|
||||
systemCursorChannel->ProcessRawInputEvent(m_cursorPosition->m_normalizedPositionDelta.GetLength());
|
||||
// Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation
|
||||
// of cursor movement velocity.
|
||||
movementXChannel->ProcessRawInputEvent(
|
||||
m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast<float>(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF());
|
||||
movementYChannel->ProcessRawInputEvent(
|
||||
m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast<float>(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF());
|
||||
mouseWheelChannel->ProcessRawInputEvent(0.f);
|
||||
|
||||
NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(movementXChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(movementYChannel, nullptr);
|
||||
NotifyUpdateChannelIfNotIdle(mouseWheelChannel, nullptr);
|
||||
}
|
||||
|
||||
@@ -318,16 +341,42 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Vector2 QtEventToAzInputMapper::WidgetPositionToNormalizedPosition(QPoint position)
|
||||
{
|
||||
const float normalizedX = aznumeric_cast<float>(position.x()) / aznumeric_cast<float>(m_sourceWidget->width());
|
||||
const float normalizedY = aznumeric_cast<float>(position.y()) / aznumeric_cast<float>(m_sourceWidget->height());
|
||||
return AZ::Vector2{normalizedX, normalizedY};
|
||||
}
|
||||
|
||||
QPoint QtEventToAzInputMapper::NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition)
|
||||
{
|
||||
const int denormalizedX = aznumeric_cast<int>(normalizedPosition.GetX() * m_sourceWidget->width());
|
||||
const int denormalizedY = aznumeric_cast<int>(normalizedPosition.GetY() * m_sourceWidget->height());
|
||||
return QPoint{denormalizedX, denormalizedY};
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
AZ::Vector2 lastCursorPosition = m_cursorPosition->m_normalizedPosition;
|
||||
|
||||
const QPoint mousePos = mouseEvent->pos();
|
||||
const float normalizedX = aznumeric_cast<float>(mousePos.x()) / aznumeric_cast<float>(m_sourceWidget->width());
|
||||
const float normalizedY = aznumeric_cast<float>(mousePos.y()) / aznumeric_cast<float>(m_sourceWidget->height());
|
||||
const AZ::Vector2 normalizedPosition(normalizedX, normalizedY);
|
||||
const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos);
|
||||
m_cursorPosition->m_normalizedPositionDelta = normalizedPosition - m_cursorPosition->m_normalizedPosition;
|
||||
m_cursorPosition->m_normalizedPosition = normalizedPosition;
|
||||
ProcessPendingMouseEvents();
|
||||
m_mouseChannelsNeedUpdate = true;
|
||||
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
// Reset our cursor position to the previous point.
|
||||
QPoint targetScreenPosition = m_sourceWidget->mapToGlobal(NormalizedPositionToWidgetPosition(lastCursorPosition));
|
||||
AzQtComponents::SetCursorPos(targetScreenPosition);
|
||||
|
||||
// Even though we just set the cursor position, there are edge cases such as remote desktop that will leave
|
||||
// the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation.
|
||||
QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos());
|
||||
m_cursorPosition->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleKeyEvent(QKeyEvent* keyEvent)
|
||||
|
||||
@@ -47,6 +47,12 @@ namespace AzToolsFramework
|
||||
//! Sets whether or not this input mapper should be updating its input channels from Qt events.
|
||||
void SetEnabled(bool enabled);
|
||||
|
||||
//! Sets whether or not the cursor should be constrained to the source widget and invisible.
|
||||
//! Internally, this will reset the cursor position after each move event to ensure movement
|
||||
//! events don't allow the cursor to escape. This can be used for typical camera controls
|
||||
//! like a dolly or rotation, where mouse movement is important but cursor location is not.
|
||||
void SetCursorCaptureEnabled(bool enabled);
|
||||
|
||||
// QObject overrides...
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
@@ -106,6 +112,11 @@ namespace AzToolsFramework
|
||||
// Processes any pending mouse movement events, this allows mouse movement channels to close themselves.
|
||||
void ProcessPendingMouseEvents();
|
||||
|
||||
// Converts a point in logical source widget space [0..m_sourceWidget->size()] to normalized [0..1] space.
|
||||
AZ::Vector2 WidgetPositionToNormalizedPosition(QPoint position);
|
||||
// Converts a point in normalized [0..1] space to logical source widget space [0..m_sourceWidget->size()].
|
||||
QPoint NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition);
|
||||
|
||||
// Handle mouse click events.
|
||||
void HandleMouseButtonEvent(QMouseEvent* mouseEvent);
|
||||
// Handle mouse move events.
|
||||
@@ -144,6 +155,8 @@ namespace AzToolsFramework
|
||||
bool m_mouseChannelsNeedUpdate = false;
|
||||
// Flags whether or not Qt events should currently be processed.
|
||||
bool m_enabled = true;
|
||||
// Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement).
|
||||
bool m_capturingCursor = false;
|
||||
|
||||
// Our viewport-specific AZ devices. We control their internal input channel states.
|
||||
AZStd::unique_ptr<EditorQtMouseDevice> m_mouseDevice;
|
||||
|
||||
+11
-8
@@ -172,20 +172,23 @@ namespace AzToolsFramework
|
||||
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
|
||||
|
||||
//apply patch to template
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
|
||||
templateDomReference.GetAllocator(), providedPatch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), providedPatch);
|
||||
|
||||
//trigger propagation
|
||||
if (result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success)
|
||||
if (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Success)
|
||||
{
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
|
||||
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
|
||||
return true;
|
||||
AZ_Error("Prefab", false, "Patch was not successfully applied.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("Prefab", false, "Patch was not successfully applied");
|
||||
return false;
|
||||
AZ_Error(
|
||||
"Prefab", result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip,
|
||||
"Some of the patches are not successfully applied.");
|
||||
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
|
||||
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,12 +176,17 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::JsonSerializationResult::ResultCode applyPatchResult = AZ::JsonSerialization::ApplyPatch(
|
||||
sourceTemplateDomCopy,
|
||||
targetTemplatePrefabDom.GetAllocator(),
|
||||
patchesReference->get(),
|
||||
AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode applyPatchResult =
|
||||
PrefabDomUtils::ApplyPatches(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator(), patchesReference->get());
|
||||
linkedInstanceDom.CopyFrom(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator());
|
||||
|
||||
PrefabDomValueReference sourceTemplateName =
|
||||
PrefabDomUtils::FindPrefabDomValue(sourceTemplateDomCopy, PrefabDomUtils::SourceName);
|
||||
AZ_Assert(sourceTemplateName && sourceTemplateName->get().IsString(), "A valid source template name couldn't be found");
|
||||
PrefabDomValueReference targetTemplateName =
|
||||
PrefabDomUtils::FindPrefabDomValue(targetTemplatePrefabDom, PrefabDomUtils::SourceName);
|
||||
AZ_Assert(targetTemplateName && targetTemplateName->get().IsString(), "A valid target template name couldn't be found");
|
||||
|
||||
if (applyPatchResult.GetProcessing() != AZ::JsonSerializationResult::Processing::Completed)
|
||||
{
|
||||
AZ_Error(
|
||||
@@ -190,6 +195,14 @@ namespace AzToolsFramework
|
||||
m_sourceTemplateId, m_targetTemplateId);
|
||||
return false;
|
||||
}
|
||||
if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"Link::UpdateTarget - Some of the patches couldn't be applied on the source template '%s' present under the "
|
||||
"target Template '%s'.",
|
||||
sourceTemplateName->get().GetString(), targetTemplateName->get().GetString());
|
||||
}
|
||||
}
|
||||
|
||||
// This is a guardrail to ensure the linked instance dom always has the LinkId value
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace AzToolsFramework
|
||||
return valueIterator->value;
|
||||
}
|
||||
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom)
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags)
|
||||
{
|
||||
InstanceEntityIdMapper entityIdMapper;
|
||||
entityIdMapper.SetStoringInstance(instance);
|
||||
@@ -58,6 +58,11 @@ namespace AzToolsFramework
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
settings.m_metadata.Add(&entityIdMapper);
|
||||
|
||||
if ((flags & StoreInstanceFlags::StripDefaultValues) != StoreInstanceFlags::StripDefaultValues)
|
||||
{
|
||||
settings.m_keepDefaults = true;
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
|
||||
|
||||
@@ -231,6 +236,26 @@ namespace AzToolsFramework
|
||||
return findInstancesResult->get();
|
||||
}
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode ApplyPatches(
|
||||
PrefabDomValue& prefabDomToApplyPatchesOn, PrefabDom::AllocatorType& allocator, const PrefabDomValue& patches)
|
||||
{
|
||||
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
|
||||
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
if (result.GetProcessing() == Processing::Halted)
|
||||
{
|
||||
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
AZ::JsonApplyPatchSettings applyPatchSettings;
|
||||
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
|
||||
return AZ::JsonSerialization::ApplyPatch(
|
||||
prefabDomToApplyPatchesOn, allocator, patches, AZ::JsonMergeApproach::JsonPatch, applyPatchSettings);
|
||||
}
|
||||
|
||||
void PrintPrefabDomValue(
|
||||
[[maybe_unused]] const AZStd::string_view printMessage,
|
||||
[[maybe_unused]] const PrefabDomValue& prefabDomValue)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
@@ -36,13 +37,25 @@ namespace AzToolsFramework
|
||||
PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName);
|
||||
PrefabDomValueConstReference FindPrefabDomValue(const PrefabDomValue& parentValue, const char* valueName);
|
||||
|
||||
enum class StoreInstanceFlags : uint8_t
|
||||
{
|
||||
//! No flags used during the call to LoadInstanceFromPrefabDom.
|
||||
None = 0,
|
||||
|
||||
//! By default an instance will be stored with default values. In cases where we want to store less json without defaults
|
||||
//! such as saving to disk, this flag will control that behavior.
|
||||
StripDefaultValues = 1 << 0
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreInstanceFlags);
|
||||
|
||||
/**
|
||||
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates
|
||||
* @param instance The instance to store
|
||||
* @param prefabDom The prefabDom that will be used to store the Instance data
|
||||
* @param flags Controls behavior such as whether to store default values
|
||||
* @return bool on whether the operation succeeded
|
||||
*/
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom);
|
||||
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreInstanceFlags flags = StoreInstanceFlags::None);
|
||||
|
||||
enum class LoadInstanceFlags : uint8_t
|
||||
{
|
||||
@@ -52,13 +65,13 @@ namespace AzToolsFramework
|
||||
//! unique, e.g. when they are duplicates of live entities, this flag will assign them a random new id.
|
||||
AssignRandomEntityId = 1 << 0
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadInstanceFlags)
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(LoadInstanceFlags);
|
||||
|
||||
/**
|
||||
* Loads a valid Prefab Instance from a Prefab Dom. Useful for generating Instances.
|
||||
* @param instance The Instance to load.
|
||||
* @param prefabDom The prefabDom that will be used to load the Instance data.
|
||||
* @param shouldClearContainers Whether to clear containers in Instance while loading.
|
||||
* @param flags Controls behavior such as random entity id assignment.
|
||||
* @return bool on whether the operation succeeded.
|
||||
*/
|
||||
bool LoadInstanceFromPrefabDom(
|
||||
@@ -110,6 +123,11 @@ namespace AzToolsFramework
|
||||
*/
|
||||
PrefabDomValueConstReference GetInstancesValue(const PrefabDomValue& prefabDom);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode ApplyPatches(
|
||||
PrefabDomValue& prefabDomToApplyPatchesOn,
|
||||
PrefabDom::AllocatorType& allocator,
|
||||
const PrefabDomValue& patches);
|
||||
|
||||
/**
|
||||
* Prints the contents of the given prefab DOM value to the debug output console in a readable format.
|
||||
* @param printMessage The message that will be printed before printing the PrefabDomValue
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace AzToolsFramework
|
||||
progressedFilePathsSet.emplace(relativePath);
|
||||
|
||||
// Get 'Instances' value from Template.
|
||||
bool isLoadedWithErrors = false;
|
||||
bool isLoadSuccessful = true;
|
||||
PrefabDomValueReference instancesReference = newTemplate.GetInstancesValue();
|
||||
if (instancesReference.has_value())
|
||||
{
|
||||
@@ -185,7 +185,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (!LoadNestedInstance(instanceIterator, newTemplateId, progressedFilePathsSet))
|
||||
{
|
||||
isLoadedWithErrors = true;
|
||||
isLoadSuccessful = false;
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"PrefabLoader::LoadTemplate - "
|
||||
@@ -196,7 +196,10 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
newTemplate.MarkAsLoadedWithErrors(isLoadedWithErrors);
|
||||
|
||||
isLoadSuccessful &= SanitizeLoadedTemplate(newTemplate.GetPrefabDom());
|
||||
|
||||
newTemplate.MarkAsLoadedWithErrors(!isLoadSuccessful);
|
||||
|
||||
// Un-mark the file as being in progress.
|
||||
progressedFilePathsSet.erase(originPath);
|
||||
@@ -277,6 +280,63 @@ namespace AzToolsFramework
|
||||
return !nestedTemplateReference->get().IsLoadedWithErrors();
|
||||
}
|
||||
|
||||
bool PrefabLoader::SanitizeLoadedTemplate(PrefabDomReference loadedTemplateDom)
|
||||
{
|
||||
// Prefabs are stored to disk with default values stripped. However, while in memory, we need those default values to be
|
||||
// present to make patches work consistently. To accomplish this, we'll instantiate the Dom, then serialize the instance
|
||||
// back into a Dom with all of the default values preserved.
|
||||
// Note that this is the default behavior in Prefab serialization, so we don't need to specify StoreInstanceFlags.
|
||||
|
||||
if (!loadedTemplateDom)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance loadedPrefabInstance;
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(loadedPrefabInstance, loadedTemplateDom->get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PrefabDom storedPrefabDom(&loadedTemplateDom->get().GetAllocator());
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(loadedPrefabInstance, storedPrefabDom))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
loadedTemplateDom->get().CopyFrom(storedPrefabDom, loadedTemplateDom->get().GetAllocator());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrefabLoader::SanitizeSavingTemplate(PrefabDomReference savingTemplateDom)
|
||||
{
|
||||
// Prefabs are stored in memory with default values spelled out to make patches work consistently. However, when we store them
|
||||
// to disk, we strip those default values to save on file size. To accomplish this, we'll instantiate the Dom, then serialize
|
||||
// the instance back into a Dom with all of the default values stripped.
|
||||
|
||||
if (!savingTemplateDom)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance savingPrefabInstance;
|
||||
if (!PrefabDomUtils::LoadInstanceFromPrefabDom(savingPrefabInstance, savingTemplateDom->get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PrefabDom storedPrefabDom(&savingTemplateDom->get().GetAllocator());
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(savingPrefabInstance, storedPrefabDom,
|
||||
PrefabDomUtils::StoreInstanceFlags::StripDefaultValues))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
savingTemplateDom->get().CopyFrom(storedPrefabDom, savingTemplateDom->get().GetAllocator());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrefabLoader::SaveTemplate(TemplateId templateId)
|
||||
{
|
||||
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
|
||||
@@ -395,7 +455,7 @@ namespace AzToolsFramework
|
||||
|
||||
// Make a copy of a our prefab DOM where nested instances become file references with patch data
|
||||
PrefabDom templateDomToSave;
|
||||
if (!templateToSave.CopyTemplateIntoPrefabFileFormat(templateDomToSave))
|
||||
if (!CopyTemplateIntoPrefabFileFormat(templateToSave, templateDomToSave))
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
@@ -410,6 +470,80 @@ namespace AzToolsFramework
|
||||
return { { AZStd::move(templateDomToSave), templateToSave.GetFilePath() } };
|
||||
}
|
||||
|
||||
bool PrefabLoader::CopyTemplateIntoPrefabFileFormat(TemplateReference templateRef, PrefabDom& output)
|
||||
{
|
||||
AZ_Assert(
|
||||
templateRef.has_value(),
|
||||
"CopyTemplateIntoPrefabFileFormat called on empty template reference."
|
||||
);
|
||||
|
||||
PrefabDom& prefabDom = templateRef->get().GetPrefabDom();
|
||||
|
||||
// Start by making a copy of our dom
|
||||
output.CopyFrom(prefabDom, prefabDom.GetAllocator());
|
||||
|
||||
SanitizeSavingTemplate(output);
|
||||
|
||||
for (const LinkId& linkId : templateRef->get().GetLinks())
|
||||
{
|
||||
AZStd::optional<AZStd::reference_wrapper<Link>> findLinkResult = m_prefabSystemComponentInterface->FindLink(linkId);
|
||||
|
||||
if (!findLinkResult.has_value())
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"Link with id %llu could not be found while attempting to store "
|
||||
"Prefab Template with source path %s in Prefab File format. "
|
||||
"Unable to proceed.",
|
||||
linkId, templateRef->get().GetFilePath().c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!findLinkResult->get().IsValid())
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"Link with id %llu and is invalid during attempt to store "
|
||||
"Prefab Template with source path %s in Prefab File format. "
|
||||
"Unable to Proceed.",
|
||||
linkId, templateRef->get().GetFilePath().c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Link& link = findLinkResult->get();
|
||||
|
||||
PrefabDomPath instancePath = link.GetInstancePath();
|
||||
PrefabDom& linkDom = link.GetLinkDom();
|
||||
|
||||
// Get the instance value of the Template copy
|
||||
// This currently stores a fully realized nested Template Dom
|
||||
PrefabDomValue* instanceValue = instancePath.Get(output);
|
||||
|
||||
if (!instanceValue)
|
||||
{
|
||||
AZ_Error(
|
||||
"Prefab", false,
|
||||
"Template::CopyTemplateIntoPrefabFileFormat: Unable to recover nested instance Dom value from link with id %llu "
|
||||
"while attempting to store a collapsed version of a Prefab Template with source path %s. Unable to proceed.",
|
||||
linkId, templateRef->get().GetFilePath().c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the contents of the Link to overwrite our Template Dom copies Instance
|
||||
// The instance is now "collapsed" as it contains the file reference and patches from the link
|
||||
instanceValue->CopyFrom(linkDom, prefabDom.GetAllocator());
|
||||
}
|
||||
|
||||
// Remove Source parameter from the dom. It will be added on file load, and should not be stored to disk.
|
||||
PrefabDomPath sourcePath = PrefabDomPath((AZStd::string("/") + PrefabDomUtils::SourceName).c_str());
|
||||
sourcePath.Erase(output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrefabLoader::IsValidPrefabPath(AZ::IO::PathView path)
|
||||
{
|
||||
// Check for OS invalid character and paths ending on '/' '\\' separators as final char
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace AzToolsFramework
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabSystemComponentInterface;
|
||||
class Template;
|
||||
using TemplateReference = AZStd::optional<AZStd::reference_wrapper<Template>>;
|
||||
|
||||
/**
|
||||
* The Prefab Loader helps saving/loading Prefab files.
|
||||
@@ -106,6 +108,16 @@ namespace AzToolsFramework
|
||||
static bool IsValidPrefabPath(AZ::IO::PathView path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Copies the template dom provided and manipulates it into the proper format to be saved to disk.
|
||||
* @param templateRef The template whose dom we want to transform into the proper format to be saved to disk.
|
||||
* @param[out] output The PrefabDom reference we want to store the result into.
|
||||
* @return True if the operation was completed correctly, false otherwise.
|
||||
*/
|
||||
bool CopyTemplateIntoPrefabFileFormat(
|
||||
TemplateReference templateRef,
|
||||
PrefabDom& output
|
||||
);
|
||||
|
||||
/**
|
||||
* Load Prefab Template from given file path to memory and return the id of loaded Template.
|
||||
@@ -141,6 +153,20 @@ namespace AzToolsFramework
|
||||
TemplateId targetTemplateId,
|
||||
AZStd::unordered_set<AZ::IO::Path>& progressedFilePathsSet);
|
||||
|
||||
/*
|
||||
* Manipulate the provided PrefabDom into the right format to be stored in memory for editor usage.
|
||||
* @param loadedTemplateDom The template to manipulate. Changes will be applied in place.
|
||||
* @return True if the manipulations where applied correctly, false otherwise.
|
||||
*/
|
||||
bool SanitizeLoadedTemplate(PrefabDomReference loadedTemplateDom);
|
||||
|
||||
/*
|
||||
* Manipulate the provided PrefabDom into the right format to be stored to disk.
|
||||
* @param savingTemplateDom The template to manipulate. Changes will be applied in place.
|
||||
* @return True if the manipulations where applied correctly, false otherwise.
|
||||
*/
|
||||
bool SanitizeSavingTemplate(PrefabDomReference savingTemplateDom);
|
||||
|
||||
//! Retrieves Dom content and its path from a template id
|
||||
AZStd::optional<AZStd::pair<PrefabDom, AZ::IO::Path>> StoreTemplateIntoFileFormat(TemplateId templateId);
|
||||
|
||||
|
||||
@@ -631,13 +631,16 @@ namespace AzToolsFramework
|
||||
//member itself, so we need to move instancesValue to the correct position for the next insert
|
||||
memberFound = instancesValue->get().FindMember(PrefabDomUtils::InstancesName);
|
||||
instancesValue = memberFound->value;
|
||||
instancesValue->get().SetObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
instancesValue = memberFound->value;
|
||||
}
|
||||
|
||||
if (!instancesValue->get().IsObject())
|
||||
{
|
||||
instancesValue->get().SetObject();
|
||||
}
|
||||
// Only add the instance if it's not there already
|
||||
if (instancesValue->get().FindMember(rapidjson::StringRef(instanceAlias.c_str())) == instancesValue->get().MemberEnd())
|
||||
{
|
||||
|
||||
@@ -261,8 +261,13 @@ namespace AzToolsFramework
|
||||
instanceDom.CopyFrom(instanceDomRef->get(), instanceDom.GetAllocator());
|
||||
|
||||
//apply the patch to the template within the target
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(instanceDom,
|
||||
instanceDom.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(instanceDom, instanceDom.GetAllocator(), patch);
|
||||
|
||||
AZ_Error(
|
||||
"Prefab",
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip ||
|
||||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
|
||||
"Some of the patches are not successfully applied.");
|
||||
|
||||
//remove the link id placed into the instance
|
||||
auto linkIdIter = instanceDom.FindMember(PrefabDomUtils::LinkIdName);
|
||||
|
||||
@@ -138,77 +138,6 @@ namespace AzToolsFramework
|
||||
return m_prefabDom;
|
||||
}
|
||||
|
||||
bool Template::CopyTemplateIntoPrefabFileFormat(PrefabDom& output)
|
||||
{
|
||||
// Start by making a copy of our dom
|
||||
output.CopyFrom(m_prefabDom, m_prefabDom.GetAllocator());
|
||||
|
||||
PrefabSystemComponentInterface* prefabSystemComponentInterface =
|
||||
AZ::Interface<PrefabSystemComponentInterface>::Get();
|
||||
|
||||
AZ_Assert(prefabSystemComponentInterface,
|
||||
"Prefab - Prefab System Component Interface is null while attempting "
|
||||
"to copy Template associated with Prefab file %s into Prefab File format",
|
||||
m_filePath.c_str());
|
||||
|
||||
for (const LinkId& linkId : m_links)
|
||||
{
|
||||
AZStd::optional<AZStd::reference_wrapper<Link>> findLinkResult =
|
||||
prefabSystemComponentInterface->FindLink(linkId);
|
||||
|
||||
if (!findLinkResult.has_value())
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
"Link with id %llu could not be found while attempting to store "
|
||||
"Prefab Template with source path %s in Prefab File format. "
|
||||
"Unable to proceed.",
|
||||
linkId, m_filePath.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!findLinkResult->get().IsValid())
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
"Link with id %llu and is invalid during attempt to store "
|
||||
"Prefab Template with source path %s in Prefab File format. "
|
||||
"Unable to Proceed.",
|
||||
linkId, m_filePath.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Link& link = findLinkResult->get();
|
||||
|
||||
PrefabDomPath instancePath = link.GetInstancePath();
|
||||
PrefabDom& linkDom = link.GetLinkDom();
|
||||
|
||||
// Get the instance value of the Template copy
|
||||
// This currently stores a fully realized nested Template Dom
|
||||
PrefabDomValue* instanceValue = instancePath.Get(output);
|
||||
|
||||
if (!instanceValue)
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
"Template::CopyTemplateIntoPrefabFileFormat: Unable to recover nested instance Dom value from link with id %llu "
|
||||
"while attempting to store a collapsed version of a Prefab Template with source path %s. Unable to proceed.",
|
||||
linkId, m_filePath.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the contents of the Link to overwrite our Template Dom copies Instance
|
||||
// The instance is now "collapsed" as it contains the file reference and patches from the link
|
||||
instanceValue->CopyFrom(linkDom, m_prefabDom.GetAllocator());
|
||||
}
|
||||
|
||||
// Remove Source parameter from the dom. It will be added on file load, and should not be stored to disk.
|
||||
PrefabDomPath sourcePath = PrefabDomPath((AZStd::string("/") + PrefabDomUtils::SourceName).c_str());
|
||||
sourcePath.Erase(output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PrefabDomValueReference Template::GetInstancesValue()
|
||||
{
|
||||
if (!IsValid())
|
||||
|
||||
@@ -58,8 +58,6 @@ namespace AzToolsFramework
|
||||
PrefabDom& GetPrefabDom();
|
||||
const PrefabDom& GetPrefabDom() const;
|
||||
|
||||
bool CopyTemplateIntoPrefabFileFormat(PrefabDom& output);
|
||||
|
||||
PrefabDomValueReference GetInstancesValue();
|
||||
PrefabDomValueConstReference GetInstancesValue() const;
|
||||
|
||||
|
||||
+18
-1
@@ -34,7 +34,24 @@ namespace AzToolsFramework
|
||||
|
||||
bool EntityOutlinerSortFilterProxyModel::lessThan(const QModelIndex& leftIndex, const QModelIndex& rightIndex) const
|
||||
{
|
||||
return sourceModel()->data(leftIndex).toString() < sourceModel()->data(rightIndex).toString();
|
||||
if (leftIndex.isValid() && rightIndex.isValid())
|
||||
{
|
||||
QVariant leftData = sourceModel()->data(leftIndex);
|
||||
QVariant rightData = sourceModel()->data(rightIndex);
|
||||
|
||||
// make sure to compare the correct data types for sorting the current column
|
||||
AZ_Assert(leftData.type() == rightData.type(), "EntityOutlinerSortFilterProxyModel::lessThan types do not agree!");
|
||||
if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::QString)
|
||||
{
|
||||
return leftData.toString() < rightData.toString();
|
||||
}
|
||||
else if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::ULongLong)
|
||||
{
|
||||
return leftData.toULongLong() < rightData.toULongLong();
|
||||
}
|
||||
AZ_Error("Editor", false, "Error! Unhandled type \"%s\" in EntityOutlinerSortFilterProxyModel::lessThan", leftData.typeName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityOutlinerSortFilterProxyModel::sort(int /*column*/, Qt::SortOrder /*order*/)
|
||||
|
||||
+15
-4
@@ -291,10 +291,12 @@ namespace AzToolsFramework
|
||||
GetEntityContextId());
|
||||
EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
EntityOutlinerWidget::~EntityOutlinerWidget()
|
||||
{
|
||||
EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
@@ -1106,16 +1108,25 @@ namespace AzToolsFramework
|
||||
AzQtComponents::SetWidgetInteractEnabled(entityOutlinerUi->m_searchWidget, on);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::EnableUi(bool enable)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, enable);
|
||||
setEnabled(enable);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
EnableUi(enable);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, false);
|
||||
setEnabled(false);
|
||||
EnableUi(false);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
setEnabled(true);
|
||||
SetEntityOutlinerState(m_gui, true);
|
||||
EnableUi(true);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnPrefabInstancePropagationBegin()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/base.h>
|
||||
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -58,6 +59,7 @@ namespace AzToolsFramework
|
||||
, private EditorEntityInfoNotificationBus::Handler
|
||||
, private ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private Prefab::PrefabPublicNotificationBus::Handler
|
||||
, private EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -105,6 +107,9 @@ namespace AzToolsFramework
|
||||
void OnPrefabInstancePropagationBegin() override;
|
||||
void OnPrefabInstancePropagationEnd() override;
|
||||
|
||||
// EditorWindowUIRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
// Build a selection object from the given entities. Entities already in the Widget's selection buffers are ignored.
|
||||
template <class EntityIdCollection>
|
||||
QItemSelection BuildSelectionFromEntities(const EntityIdCollection& entityIds);
|
||||
@@ -155,6 +160,7 @@ namespace AzToolsFramework
|
||||
AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index) const;
|
||||
QModelIndex GetIndexFromEntityId(const AZ::EntityId& entityId) const;
|
||||
void ExtractEntityIdsFromSelection(const QItemSelection& selection, EntityIdList& entityIdList) const;
|
||||
void EnableUi(bool enable);
|
||||
|
||||
// OutlinerModelNotificationBus::Handler
|
||||
// Receive notification from the outliner model that we should scroll
|
||||
|
||||
+23
@@ -376,6 +376,7 @@ namespace AzToolsFramework
|
||||
ToolsApplicationEvents::Bus::Handler::BusConnect();
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusConnect();
|
||||
EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
m_spacer = nullptr;
|
||||
|
||||
m_emptyIcon = QIcon();
|
||||
@@ -421,6 +422,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
qApp->removeEventFilter(this);
|
||||
|
||||
EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusDisconnect();
|
||||
ToolsApplicationEvents::Bus::Handler::BusDisconnect();
|
||||
AZ::EntitySystemBus::Handler::BusDisconnect();
|
||||
@@ -4961,6 +4963,27 @@ namespace AzToolsFramework
|
||||
EnableDisableComponentActions(widget, actions, false);
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
EnableComponentActions(this, m_entityComponentActions);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableComponentActions(this, m_entityComponentActions);
|
||||
}
|
||||
m_disabled = !enable;
|
||||
SetPropertyEditorState(m_gui, enable);
|
||||
|
||||
for (auto componentEditor : m_componentEditors)
|
||||
{
|
||||
AzQtComponents::SetWidgetInteractEnabled(componentEditor, enable);
|
||||
}
|
||||
// record the selected state after entering/leaving component mode
|
||||
SaveComponentEditorState();
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
DisableComponentActions(this, m_entityComponentActions);
|
||||
|
||||
+5
@@ -21,6 +21,7 @@
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzToolsFramework/Undo/UndoSystem.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EntityPropertyEditorRequestsBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
@@ -108,6 +109,7 @@ namespace AzToolsFramework
|
||||
, public EditorInspectorComponentNotificationBus::MultiHandler
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, public AZ::EntitySystemBus::Handler
|
||||
, private EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -208,6 +210,9 @@ namespace AzToolsFramework
|
||||
void GetSelectedEntities(EntityIdList& selectedEntityIds) override;
|
||||
void SetNewComponentId(AZ::ComponentId componentId) override;
|
||||
|
||||
// EditorWindowRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
bool IsEntitySelected(const AZ::EntityId& id) const;
|
||||
bool IsSingleEntitySelected(const AZ::EntityId& id) const;
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ namespace AzToolsFramework
|
||||
/// @name Reverse URLs.
|
||||
/// Used to identify common actions and override them when necessary.
|
||||
//@{
|
||||
static const AZ::Crc32 s_backAction = AZ_CRC("com.amazon.action.common.back", 0xd772a2af);
|
||||
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.amazon.action.common.delete", 0x5731f6cb);
|
||||
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.amazon.action.common.duplicate", 0x08ccf461);
|
||||
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.amazon.action.common.nextComponentMode", 0xcc26094f);
|
||||
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.amazon.action.common.previousComponentMode", 0x0d18ff39);
|
||||
static const AZ::Crc32 s_backAction = AZ_CRC("com.o3de.action.common.back", 0xd772a2af);
|
||||
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.o3de.action.common.delete", 0x5731f6cb);
|
||||
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.o3de.action.common.duplicate", 0x08ccf461);
|
||||
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.o3de.action.common.nextComponentMode", 0xcc26094f);
|
||||
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.o3de.action.common.previousComponentMode", 0x0d18ff39);
|
||||
//@}
|
||||
|
||||
/// Specific Action properties to be sent to a type implementing
|
||||
|
||||
@@ -276,11 +276,6 @@ namespace AzToolsFramework
|
||||
virtual void EndCursorCapture() = 0;
|
||||
//! Gets the most recent recorded cursor position in the viewport in screen space coordinates.
|
||||
virtual AzFramework::ScreenPoint ViewportCursorScreenPosition() = 0;
|
||||
//! Gets the cursor position recorded prior to the most recent cursor position.
|
||||
//! Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
|
||||
//! from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
|
||||
//! position delta.
|
||||
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
|
||||
//! Is mouse over viewport.
|
||||
virtual bool IsMouseOver() const = 0;
|
||||
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
}
|
||||
|
||||
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.amazon.action.---").
|
||||
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.o3de.action.---").
|
||||
AZStd::vector<AZStd::function<void()>> m_callbacks; //!< Callbacks associated with this Action (note: with multi-selections
|
||||
//!< there will be a callback per Entity/Component).
|
||||
AZStd::unique_ptr<QAction> m_action; //!< The QAction associated with the overrideWidget for all ComponentMode actions.
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::vector<AzToolsFramework::ActionOverride> PlaceHolderComponentMode::PopulateActionsImpl()
|
||||
{
|
||||
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.amazon.action.placeholder.test");
|
||||
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.o3de.action.placeholder.test");
|
||||
|
||||
return AZStd::vector<AzToolsFramework::ActionOverride>
|
||||
{
|
||||
|
||||
@@ -96,8 +96,8 @@ namespace UnitTest
|
||||
|
||||
//apply the patch
|
||||
PrefabDom& templateDomReference = m_prefabSystemComponent->FindTemplateDom(nestedTemplateId);
|
||||
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
|
||||
templateDomReference.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), patch);
|
||||
|
||||
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
|
||||
"Patch was not successfully applied");
|
||||
|
||||
@@ -428,8 +428,7 @@ namespace UnitTest
|
||||
ASSERT_TRUE(PrefabDomUtils::StoreInstanceInPrefabDom(*newInstance, updatedDom));
|
||||
newTemplateDom.CopyFrom(updatedDom, newTemplateDom.GetAllocator());
|
||||
|
||||
// Validate that the prefabTestComponent in the Template's DOM doesn't have a BoolProperty.
|
||||
// Even though we changed the property to false, it won't be serialized out because it's a default value.
|
||||
// Validate that the value of the BoolProperty of the prefabTestComponent in the Template's DOM has changed.
|
||||
entityComponents = PrefabTestDomUtils::GetPrefabDomComponents(newTemplateDom, newTemplateEntityAliases.front());
|
||||
ASSERT_TRUE(entityComponents != nullptr && entityComponents->IsObject());
|
||||
EXPECT_EQ(entityComponents->MemberCount(), 2);
|
||||
@@ -440,7 +439,7 @@ namespace UnitTest
|
||||
|
||||
PrefabDomValueConstReference wheelEntityComponentBoolPropertyValue =
|
||||
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponentValue->get(), PrefabTestDomUtils::BoolPropertyName);
|
||||
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
|
||||
ASSERT_TRUE(wheelEntityComponentBoolPropertyValue.has_value() && wheelEntityComponentBoolPropertyValue->get() == false);
|
||||
|
||||
// Update Template's Instances and validate if all Instances have no BoolProperty under their prefabTestComponents in entities.
|
||||
m_instanceUpdateExecutorInterface->AddTemplateInstancesToQueue(newTemplateId);
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace UnitTest
|
||||
EntityAlias entityAlias = wheelTemplateEntityAliases.front();
|
||||
PrefabDomValue* wheelEntityComponents =
|
||||
PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
|
||||
ASSERT_TRUE(wheelEntityComponents == nullptr);
|
||||
ASSERT_TRUE(wheelEntityComponents->IsArray() && wheelEntityComponents->Size() == 0);
|
||||
|
||||
// Create an axle with 0 entities and 1 wheel instance.
|
||||
AZStd::unique_ptr<Instance> wheel1UnderAxle = m_prefabSystemComponent->InstantiatePrefab(wheelTemplateId);
|
||||
@@ -340,7 +340,7 @@ namespace UnitTest
|
||||
|
||||
// Validate that the wheel entity does not have a component under it.
|
||||
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
|
||||
ASSERT_TRUE(wheelEntityComponents == nullptr);
|
||||
ASSERT_TRUE(wheelEntityComponents->IsArray() && wheelEntityComponents->Size() == 0);
|
||||
|
||||
// Validate that the wheels under the axle have the same DOM as the wheel template.
|
||||
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom);
|
||||
@@ -399,15 +399,14 @@ namespace UnitTest
|
||||
m_prefabSystemComponent->UpdatePrefabTemplate(wheelTemplateId, updatedWheelInstanceDom);
|
||||
m_instanceUpdateExecutorInterface->UpdateTemplateInstancesInQueue();
|
||||
|
||||
// Validate that the prefabTestComponent in the wheel template DOM doesn't have a BoolProperty.
|
||||
// Even though we changed the property to false, it won't be serialized out because it's a default value.
|
||||
// Validate that the BoolProperty of the prefabTestComponent in the wheel template DOM is set to false.
|
||||
wheelEntityComponents = PrefabTestDomUtils::GetPrefabDomComponentsPath(entityAlias).Get(wheelTemplateDom);
|
||||
ASSERT_TRUE(wheelEntityComponents != nullptr && wheelEntityComponents->IsObject());
|
||||
EXPECT_EQ(wheelEntityComponents->MemberCount(), 1);
|
||||
|
||||
PrefabDomValueReference wheelEntityComponentBoolPropertyValue =
|
||||
PrefabDomUtils::FindPrefabDomValue(wheelEntityComponents->MemberBegin()->value, PrefabTestDomUtils::BoolPropertyName);
|
||||
ASSERT_FALSE(wheelEntityComponentBoolPropertyValue.has_value());
|
||||
ASSERT_TRUE(wheelEntityComponentBoolPropertyValue.has_value() && wheelEntityComponentBoolPropertyValue->get() == false);
|
||||
|
||||
// Validate that the wheels under the axle have the same DOM as the wheel template.
|
||||
PrefabTestDomUtils::ValidatePrefabDomInstances(wheelInstanceAliasesUnderAxle, axleTemplateDom, wheelTemplateDom);
|
||||
|
||||
@@ -174,6 +174,42 @@ namespace LegacyLevelSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure a spawnable level exists that matches levelname
|
||||
AZStd::string validLevelName = "";
|
||||
AZ::Data::AssetId rootSpawnableAssetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
rootSpawnableAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, levelName, nullptr, false);
|
||||
|
||||
if (rootSpawnableAssetId.IsValid())
|
||||
{
|
||||
validLevelName = levelName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's common for users to only provide the level name, but not the full asset path
|
||||
// Example: "MyLevel" instead of "Levels/MyLevel/MyLevel.spawnable"
|
||||
if (!AZ::IO::PathView(levelName).HasExtension())
|
||||
{
|
||||
// Search inside the "Levels" folder for a level spawnable matching levelname
|
||||
const AZStd::string possibleLevelAssetPath = AZStd::string::format("Levels/%s/%s.spawnable", levelName, levelName);
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
rootSpawnableAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, possibleLevelAssetPath.c_str(),
|
||||
nullptr, false);
|
||||
|
||||
if (rootSpawnableAssetId.IsValid())
|
||||
{
|
||||
validLevelName = possibleLevelAssetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (validLevelName.empty())
|
||||
{
|
||||
OnLevelNotFound(levelName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a level is currently loaded, unload it before loading the next one.
|
||||
if (IsLevelLoaded())
|
||||
{
|
||||
@@ -181,12 +217,12 @@ namespace LegacyLevelSystem
|
||||
}
|
||||
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_LOAD_PREPARE, 0, 0);
|
||||
PrepareNextLevel(levelName);
|
||||
PrepareNextLevel(validLevelName.c_str());
|
||||
|
||||
bool result = LoadLevelInternal(levelName);
|
||||
bool result = LoadLevelInternal(validLevelName.c_str());
|
||||
if (result)
|
||||
{
|
||||
OnLoadingComplete(levelName);
|
||||
OnLoadingComplete(validLevelName.c_str());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace AWSNativeSDKInit
|
||||
#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK)
|
||||
void CustomizeSDKOptions(Aws::SDKOptions& options);
|
||||
void CustomizeShutdown();
|
||||
|
||||
void CopyCaCertBundle();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -44,6 +46,8 @@ namespace AWSNativeSDKInit
|
||||
void InitializationManager::InitAwsApi()
|
||||
{
|
||||
s_initManager = AZ::Environment::CreateVariable<InitializationManager>(initializationManagerTag);
|
||||
|
||||
Platform::CopyCaCertBundle();
|
||||
}
|
||||
|
||||
void InitializationManager::Shutdown()
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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/PlatformDef.h>
|
||||
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
|
||||
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
|
||||
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
|
||||
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
|
||||
// this warning.
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
||||
#include <aws/core/utils/memory/stl/AWSString.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AWSNativeSDKInit
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
void CopyCaCertBundle()
|
||||
{
|
||||
AZStd::vector<char> contents;
|
||||
AZStd::string certificatePath = "@assets@/certificates/aws/cacert.pem";
|
||||
AZStd::string publicStoragePath = AZ::Android::Utils::GetAppPublicStoragePath();
|
||||
publicStoragePath.append("/certificates/aws/cacert.pem");
|
||||
|
||||
AZ::IO::FileIOBase* fileBase = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
if (!fileBase->Exists(certificatePath.c_str()))
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Certificate File(%s) does not exist.\n", certificatePath.c_str());
|
||||
}
|
||||
|
||||
AZ::IO::HandleType fileHandle;
|
||||
AZ::IO::Result fileResult = fileBase->Open(certificatePath.c_str(), AZ::IO::OpenMode::ModeRead, fileHandle);
|
||||
|
||||
if (!fileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to open certificate file with result %i\n", fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ::u64 fileSize = 0;
|
||||
fileBase->Size(fileHandle, fileSize);
|
||||
|
||||
if (fileSize == 0)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Given empty file(%s) as the certificate bundle.\n", certificatePath.c_str());
|
||||
}
|
||||
|
||||
contents.resize(fileSize + 1);
|
||||
fileResult = fileBase->Read(fileHandle, contents.data(), fileSize);
|
||||
|
||||
if (!fileResult)
|
||||
{
|
||||
AZ_Error(
|
||||
"AWSNativeSDKInit", false, "Failed to read from the certificate bundle(%s) with result code(%i).\n", certificatePath.c_str(),
|
||||
fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ_Printf("AWSNativeSDKInit", "Certificate bundle is read successfully from %s", certificatePath.c_str());
|
||||
|
||||
AZ::IO::HandleType outFileHandle;
|
||||
|
||||
AZ::IO::Result outFileResult = fileBase->Open(publicStoragePath.c_str(), AZ::IO::OpenMode::ModeWrite, outFileHandle);
|
||||
|
||||
if (!outFileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to open the certificate bundle with result %i\n", fileResult.GetResultCode());
|
||||
}
|
||||
|
||||
AZ::IO::Result writeFileResult = fileBase->Write(outFileHandle, contents.data(), fileSize);
|
||||
if (!writeFileResult)
|
||||
{
|
||||
AZ_Error("AWSNativeSDKInit", false, "Failed to write the certificate bundle with result %i\n", writeFileResult.GetResultCode());
|
||||
}
|
||||
|
||||
fileBase->Close(fileHandle);
|
||||
fileBase->Close(outFileHandle);
|
||||
|
||||
AZ_Printf("AWSNativeSDKInit", "Certificate bundle successfully copied to %s", publicStoragePath.c_str());
|
||||
}
|
||||
} // namespace Platform
|
||||
}
|
||||
@@ -7,4 +7,5 @@
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AWSNativeSDKInit_Default.cpp
|
||||
InitializeCerts_Android.cpp
|
||||
)
|
||||
|
||||
+16
-18
@@ -1,18 +1,16 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace News {
|
||||
enum LogType
|
||||
{
|
||||
LogOk,
|
||||
LogInfo,
|
||||
LogError,
|
||||
LogWarning
|
||||
};
|
||||
} // namespace News
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
namespace AWSNativeSDKInit
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
void CopyCaCertBundle()
|
||||
{
|
||||
}
|
||||
} // namespace Platform
|
||||
} // namespace AWSCore
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user