Merge branch 'main' into ly-as-sdk/LYN-2948
This commit is contained in:
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# Test case ID : C18977329
|
||||
# Test Case Title : Add cloth simulation to a Mesh
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/18977329
|
||||
|
||||
# fmt: off
|
||||
class Tests:
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# Test case ID : C18977330
|
||||
# Test Case Title : Add cloth simulation to an Actor
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/18977330
|
||||
|
||||
# fmt: off
|
||||
class Tests:
|
||||
|
||||
@@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# Test case ID : C28798177
|
||||
# Test Case Title : White Box Tool Component can be added to an Entity
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/28798177
|
||||
|
||||
|
||||
# fmt:off
|
||||
|
||||
@@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# Test case ID : C28798205
|
||||
# Test Case Title : From the White Box Component Card the White Box Mesh can be set to be invisible in Game View
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/28798205
|
||||
|
||||
|
||||
# fmt:off
|
||||
|
||||
@@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
# Test case ID : C29279329
|
||||
# Test Case Title : White Box mesh shape can be changed with the Default Shape dropdown on the Component
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/29279329
|
||||
|
||||
|
||||
# fmt:off
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ def C14976308_ScriptCanvas_SetKinematicTargetTransform():
|
||||
the script deactivates Signal, Sphere's transform will update to that of Transform_Target.
|
||||
NOTE: There is a known bug (LY-107723) which causes the rotation to update to a value that is not sufficiently close
|
||||
to the expected result when using Set Kinematic Target which will cause the test to fail:
|
||||
https://jira.agscollab.com/browse/LY-107723
|
||||
LY-107723
|
||||
|
||||
Test Steps:
|
||||
1) Open level and enter game mode
|
||||
|
||||
@@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# Test case ID : C3510644
|
||||
# Test Case Title : Check that the collision layer and collision group of the terrain can be changed
|
||||
# and the collision behavior of the terrain changes accordingly
|
||||
# URL of the test case : https://testrail.agscollab.com/index.php?/cases/view/3510644
|
||||
|
||||
|
||||
# fmt: off
|
||||
|
||||
@@ -239,7 +239,7 @@ def C6321601_Force_HighValuesDirectionAxes():
|
||||
force_notification_handler.add_callback("OnCalculateNetForce", on_calc_net_force)
|
||||
|
||||
# Wait for 3 secs, because there is a known bug identified and filed in
|
||||
# JIRA https://jira.agscollab.com/browse/LY-107677
|
||||
# JIRA LY-107677
|
||||
# The error "[Error] Huge object being added to a COctreeNode, name: 'MeshComponentRenderNode', objBox:"
|
||||
# will show (if occured) in about 3 sec into the game mode.
|
||||
helper.wait_for_condition(has_physx_error, 3.0)
|
||||
|
||||
@@ -50,7 +50,7 @@ class TestAutomation(TestAutomationBase):
|
||||
unexpected_lines = ["Assert"]
|
||||
self._run_test(request, workspace, editor, test_module, expected_lines, unexpected_lines)
|
||||
|
||||
# BUG: https://jira.agscollab.com/browse/LY-107723")
|
||||
# BUG: LY-107723")
|
||||
def test_C14976308_ScriptCanvas_SetKinematicTargetTransform(self, request, workspace, editor):
|
||||
from . import C14976308_ScriptCanvas_SetKinematicTargetTransform as test_module
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
'''
|
||||
This unittest might have to be refactored once changes to Physmaterial_Editor.py are made.
|
||||
These changes will occur after the but, reverence below is resloved.
|
||||
Bug: https://jira.agscollab.com/browse/LY-107392
|
||||
Bug: LY-107392
|
||||
'''
|
||||
class Tests:
|
||||
opening_bad_file = ("Bad file could not be opened", "Bad file was opened")
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569013
|
||||
Test Case Title: Script Event file can be created
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569013
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
Test case ID: T92568942
|
||||
Test Case Title: Clicking the "+" button and selecting "New Script Event" opens the
|
||||
Asset Editor with a new Script Event asset
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92568942
|
||||
"""
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
|
||||
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92568856
|
||||
Test Case Title: Multiple Entities can be targeted in the Debugger tool
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/tests/view/92568856
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569137
|
||||
Test Case Title: Multiple Graphs can be targeted in the Debugger tool
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569137
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: C1702824
|
||||
Test Case Title: Docking
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/1702824
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569049
|
||||
Test Case Title: Edit > Undo undoes the last action
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569049
|
||||
Test case ID: T92569051
|
||||
Test Case Title: Edit > Redo redoes the last undone action
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569051
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92562978
|
||||
Test Case Title: Script Canvas Component can be added to an entity
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92562978
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569037
|
||||
Test Case Title: File > New Script creates a new script
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569037
|
||||
Test case ID: T92569039
|
||||
Test Case Title: File > Open opens the Open... dialog
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569039
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
@@ -11,11 +11,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92563070
|
||||
Test Case Title: Graphs can be closed by clicking X on the Graph name tab
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92563070
|
||||
Test case ID: T92563068
|
||||
Test Case Title: Save Prompt: User is prompted to save a graph on close after
|
||||
creating a new graph
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92563068
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
@@ -11,10 +11,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569079
|
||||
Test Case Title: View > Zoom In zooms the graph in
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569079
|
||||
Test case ID: T92569081
|
||||
Test Case Title: View > Zoom In zooms the graph out
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569081
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92562988
|
||||
Test Case Title: Left-click/double click expands and collapses node categories
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92562988
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92568982
|
||||
Test Case Title: Renaming variables in the Node Inspector
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92568982
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92562993
|
||||
Test Case Title: Clicking the X button on the Search Box clears the currently entered string
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92562993
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
set_search_string = ("Search string is set", "Search string is not set")
|
||||
search_string_deleted = ("Search string deleted as expected", "Search string not deleted")
|
||||
# fmt: on
|
||||
|
||||
|
||||
def NodePalette_SearchText_Deletion():
|
||||
"""
|
||||
Summary:
|
||||
We enter some string in the Node Palette Search box, select that text and delete it.
|
||||
|
||||
Expected Behavior:
|
||||
After RightClick->Delete the text in the Searchbox should be deleted.
|
||||
|
||||
Test Steps:
|
||||
1) Open Script Canvas window (Tools > Script Canvas)
|
||||
2) Get the SC window object
|
||||
3) Open Node Manager if not opened already
|
||||
4) Set some string in the Search box
|
||||
5) Verify if the test string is set
|
||||
6) Delete search string using right click and verify if it is cleared
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Open 3D Engine Editor command terminal
|
||||
- Any passed and failed tests are written to the Editor.log file.
|
||||
Parsing the file or running a log_monitor are required to observe the test results.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
from PySide2 import QtWidgets, QtTest, QtCore
|
||||
|
||||
from utils import TestHelper as helper
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
import pyside_utils
|
||||
|
||||
TEST_STRING = "TestString"
|
||||
|
||||
# 1) Open Script Canvas window (Tools > Script Canvas)
|
||||
general.idle_enable(True)
|
||||
general.open_pane("Script Canvas")
|
||||
helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 3.0)
|
||||
|
||||
# 2) Get the SC window object
|
||||
editor_window = pyside_utils.get_editor_main_window()
|
||||
sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
|
||||
|
||||
# 3) Open Node Manager if not opened already
|
||||
if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None:
|
||||
action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction})
|
||||
action.trigger()
|
||||
node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette")
|
||||
search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame")
|
||||
|
||||
# 4) Set some string in the Search box
|
||||
search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
|
||||
search_box.setText(TEST_STRING)
|
||||
|
||||
# 5) Verify if the test string is set
|
||||
result = helper.wait_for_condition(lambda: search_box.text() == TEST_STRING, 1.0)
|
||||
Report.result(Tests.set_search_string, result)
|
||||
|
||||
# 6) Delete search string using right click and verify if it is cleared
|
||||
QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_A, QtCore.Qt.ControlModifier)
|
||||
pyside_utils.trigger_context_menu_entry(search_box, "Delete")
|
||||
result = helper.wait_for_condition(lambda: search_box.text() == "", 2.0)
|
||||
Report.result(Tests.search_string_deleted, result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import ImportPathHelper as imports
|
||||
|
||||
imports.init()
|
||||
from utils import Report
|
||||
|
||||
Report.start_test(NodePalette_SearchText_Deletion)
|
||||
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92568940
|
||||
Test Case Title: Categories and Nodes can be selected
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92568940
|
||||
"""
|
||||
|
||||
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92569253 // T92569254
|
||||
Test Case Title: On Entity Activated // On Entity Deactivated
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92569253 // https://testrail.agscollab.com/index.php?/tests/view/92569254
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: C1702834 // C1702823
|
||||
Test Case Title: Opening pane // Closing pane
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/1702834 and
|
||||
https://testrail.agscollab.com/index.php?/cases/view/1702823
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: C1702821 // C1702832
|
||||
Test Case Title: Retain visibility, size and location upon Script Canvas restart
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/1702821 and
|
||||
https://testrail.agscollab.com/index.php?/cases/view/1702832
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: C1702829
|
||||
Test Case Title: Resizing pane
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/1702829
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
Test case ID: T92562986
|
||||
Test Case Title: Changing the assigned Script Canvas Asset on an entity properly updates
|
||||
level functionality
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92562986
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92563190
|
||||
Test Case Title: A single Entity with two Script Canvas components works properly
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92563190
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92563191
|
||||
Test Case Title: Two Entities can use the same Graph asset successfully at RunTime
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92563191
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92567321
|
||||
Test Case Title: Script Events: Can send and receive a script event across multiple entities successfully
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92567321
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92567320
|
||||
Test Case Title: Script Events: Can send and receive a script event successfully
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92567320
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -195,6 +195,14 @@ class TestAutomation(TestAutomationBase):
|
||||
def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform):
|
||||
from . import NodeCategory_ExpandOnClick as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_NodePalette_SearchText_Deletion(self, request, workspace, editor, launcher_platform):
|
||||
from . import NodePalette_SearchText_Deletion as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_VariableManager_UnpinVariableType_Works(self, request, workspace, editor, launcher_platform):
|
||||
from . import VariableManager_UnpinVariableType_Works as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
# NOTE: We had to use hydra_test_utils.py, as TestAutomationBase run_test method
|
||||
# fails because of pyside_utils import
|
||||
|
||||
@@ -13,11 +13,6 @@ Test Case Title: Tools > Node Palette toggles the Node Palette
|
||||
Tools > Node Inspector toggles the Node Inspector
|
||||
Tools > Bookmarks toggles the Bookmarks
|
||||
Tools > Variable Manager toggles the Variable Manager
|
||||
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/92569165
|
||||
https://testrail.agscollab.com/index.php?/cases/view/92569167
|
||||
https://testrail.agscollab.com/index.php?/cases/view/92569168
|
||||
https://testrail.agscollab.com/index.php?/cases/view/92569170
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: C1702825 // C1702831
|
||||
Test Case Title: Undocking // Closing script canvas with the pane floating
|
||||
URLs of the test case: https://testrail.agscollab.com/index.php?/cases/view/1702825 &
|
||||
https://testrail.agscollab.com/index.php?/cases/view/1702831
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -10,10 +10,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
Test case ID: T92564789
|
||||
Test Case Title: Each Variable type can be created
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92564789
|
||||
Test case ID: T92568873
|
||||
Test Case Title: Each Variable type can be deleted
|
||||
URL of the test case: https://testrail.agscollab.com/index.php?/tests/view/92568873
|
||||
"""
|
||||
|
||||
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
variable_manager_opened = ("VariableManager is opened successfully", "Failed to open VariableManager")
|
||||
variable_pinned = ("Variable is pinned", "Variable is not pinned, But it should be unpinned")
|
||||
variable_unpinned = ("Variable is unpinned", "Variable is not unpinned, But it should be pinned")
|
||||
variable_unpinned_after_reopen = ("Variable is unpinned after reopening create variable menu", "Variable is not unpinned after reopening create variable menu")
|
||||
# fmt: on
|
||||
|
||||
|
||||
def VariableManager_UnpinVariableType_Works():
|
||||
"""
|
||||
Summary:
|
||||
Unpin variable types in create variable menu.
|
||||
Expected Behavior:
|
||||
The variable unpinned in create variable menu remains unpinned after reopening create variable menu.
|
||||
Test Steps:
|
||||
1) Open Script Canvas window (Tools > Script Canvas)
|
||||
2) Get the SC window object
|
||||
3) Open Variable Manager in Script Canvas window
|
||||
4) Create new graph
|
||||
5) Click on the Create Variable button in the Variable Manager
|
||||
6) Unpin Boolean by clicking the "Pin" icon on its left side
|
||||
7) Close and Reopen Create Variable menu and make sure Boolean is unpinned after reopening Create Variable menu
|
||||
8) Restore default layout and close SC window
|
||||
Note:
|
||||
- This test file must be called from the Open 3D Engine Editor command terminal
|
||||
- Any passed and failed tests are written to the Editor.log file.
|
||||
Parsing the file or running a log_monitor are required to observe the test results.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
from PySide2 import QtWidgets
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
import pyside_utils
|
||||
from utils import TestHelper as helper
|
||||
from utils import Report
|
||||
from PySide2.QtCore import Qt
|
||||
|
||||
GENERAL_WAIT = 1.0 # seconds
|
||||
|
||||
def find_pane(window, pane_name):
|
||||
return window.findChild(QtWidgets.QDockWidget, pane_name)
|
||||
|
||||
def click_menu_option(window, option_text):
|
||||
action = pyside_utils.find_child_by_pattern(window, {"text": option_text, "type": QtWidgets.QAction})
|
||||
action.trigger()
|
||||
|
||||
# 1) Open Script Canvas window (Tools > Script Canvas)
|
||||
general.idle_enable(True)
|
||||
general.open_pane("Script Canvas")
|
||||
helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 6.0)
|
||||
|
||||
# 2) Get the SC window object
|
||||
editor_window = pyside_utils.get_editor_main_window()
|
||||
sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
|
||||
sc_main = sc.findChild(QtWidgets.QMainWindow)
|
||||
|
||||
# 3) Open Variable Manager in Script Canvas window
|
||||
pane = find_pane(sc, "VariableManager")
|
||||
if not pane.isVisible():
|
||||
click_menu_option(sc, "Variable Manager")
|
||||
pane = find_pane(sc, "VariableManager")
|
||||
Report.result(Tests.variable_manager_opened, pane.isVisible())
|
||||
|
||||
# 4) Create new graph
|
||||
create_new_graph = pyside_utils.find_child_by_pattern(
|
||||
sc_main, {"objectName": "action_New_Script", "type": QtWidgets.QAction}
|
||||
)
|
||||
create_new_graph.trigger()
|
||||
|
||||
# 5) Click on the Create Variable button in the Variable Manager
|
||||
variable_manager = sc_main.findChild(QtWidgets.QDockWidget, "VariableManager")
|
||||
button = variable_manager.findChild(QtWidgets.QPushButton, "addButton")
|
||||
button.click()
|
||||
|
||||
# 6) Unpin Boolean by clicking the "Pin" icon on its left side
|
||||
table_view = variable_manager.findChild(QtWidgets.QTableView, "variablePalette")
|
||||
model_index = pyside_utils.find_child_by_pattern(table_view, "Boolean")
|
||||
# Make sure Boolean is pinned
|
||||
is_boolean = model_index.siblingAtColumn(0)
|
||||
result = helper.wait_for_condition(lambda: is_boolean.data(Qt.DecorationRole) is not None, GENERAL_WAIT)
|
||||
Report.result(Tests.variable_pinned, result)
|
||||
# Unpin Boolean and make sure Boolean is unpinned.
|
||||
pyside_utils.item_view_index_mouse_click(table_view, is_boolean)
|
||||
result = helper.wait_for_condition(lambda: is_boolean.data(Qt.DecorationRole) is None, GENERAL_WAIT)
|
||||
Report.result(Tests.variable_unpinned, result)
|
||||
|
||||
# 7) Close and Reopen Create Variable menu and make sure Boolean is unpinned after reopening Create Variable menu
|
||||
button.click()
|
||||
button.click()
|
||||
model_index = pyside_utils.find_child_by_pattern(table_view, "Boolean")
|
||||
result = helper.wait_for_condition(
|
||||
lambda: model_index.siblingAtColumn(0).data(Qt.DecorationRole) is None, GENERAL_WAIT
|
||||
)
|
||||
Report.result(Tests.variable_unpinned_after_reopen, result)
|
||||
|
||||
# 8) Restore default layout and close SC window
|
||||
click_menu_option(sc, "Restore Default Layout")
|
||||
general.close_pane("Script Canvas")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import ImportPathHelper as imports
|
||||
|
||||
imports.init()
|
||||
|
||||
from utils import Report
|
||||
|
||||
Report.start_test(VariableManager_UnpinVariableType_Works)
|
||||
@@ -189,7 +189,7 @@ namespace AZ
|
||||
if (!WasLoadSuccess(result.GetOutcome()))
|
||||
{
|
||||
// This if is a hack around fault in the JSON serialization system
|
||||
// Jira: https://jira.agscollab.com/browse/LY-106587
|
||||
// Jira: LY-106587
|
||||
if (message != "No part of the string could be interpreted as a uuid.")
|
||||
{
|
||||
deserializeError.append(message);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -17,4 +17,15 @@
|
||||
namespace AZStd
|
||||
{
|
||||
using std::abs;
|
||||
}
|
||||
using std::acos;
|
||||
using std::asin;
|
||||
using std::atan;
|
||||
using std::atan2;
|
||||
using std::cos;
|
||||
using std::exp2;
|
||||
using std::fmod;
|
||||
using std::round;
|
||||
using std::sin;
|
||||
using std::sqrt;
|
||||
using std::tan;
|
||||
} // namespace AZStd
|
||||
|
||||
@@ -29,14 +29,14 @@ namespace AzFramework
|
||||
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemDefaultOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 100.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemRotateSpeed, 0.005f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
@@ -125,22 +125,22 @@ namespace AzFramework
|
||||
{
|
||||
if (orientation.GetElement(2, 0) > -1.0f)
|
||||
{
|
||||
x = std::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2));
|
||||
y = std::asin(-orientation.GetElement(2, 0));
|
||||
z = std::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0));
|
||||
x = AZStd::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2));
|
||||
y = AZStd::asin(-orientation.GetElement(2, 0));
|
||||
z = AZStd::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0.0f;
|
||||
y = AZ::Constants::Pi * 0.5f;
|
||||
z = -std::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1));
|
||||
z = -AZStd::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0.0f;
|
||||
y = -AZ::Constants::Pi * 0.5f;
|
||||
z = std::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
|
||||
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
|
||||
}
|
||||
|
||||
return {x, y, z};
|
||||
@@ -150,31 +150,35 @@ namespace AzFramework
|
||||
{
|
||||
const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform));
|
||||
|
||||
camera.m_lookAt = transform.GetTranslation();
|
||||
camera.m_pitch = eulerAngles.GetX();
|
||||
camera.m_yaw = eulerAngles.GetZ();
|
||||
// note: m_lookDist is negative so we must invert it here
|
||||
camera.m_lookAt = transform.GetTranslation() + (camera.Rotation().GetBasisY() * -camera.m_lookDist);
|
||||
}
|
||||
|
||||
static ScreenVector CursorDelta(const AZStd::optional<ScreenPoint>& currentPosition, const AZStd::optional<ScreenPoint>& lastPosition)
|
||||
{
|
||||
return currentPosition.has_value() && lastPosition.has_value() ? currentPosition.value() - lastPosition.value()
|
||||
: ScreenVector(0, 0);
|
||||
}
|
||||
|
||||
bool CameraSystem::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& cursor_motion = AZStd::get_if<CursorMotionEvent>(&event))
|
||||
if (const auto& cursor = AZStd::get_if<CursorEvent>(&event))
|
||||
{
|
||||
m_currentCursorPosition = cursor_motion->m_position;
|
||||
m_currentCursorPosition = cursor->m_position;
|
||||
}
|
||||
else if (const auto& scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
m_scrollDelta = scroll->m_delta;
|
||||
}
|
||||
|
||||
return m_cameras.HandleEvents(event);
|
||||
return m_cameras.HandleEvents(event, CursorDelta(m_currentCursorPosition, m_lastCursorPosition), m_scrollDelta);
|
||||
}
|
||||
|
||||
Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime)
|
||||
{
|
||||
const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value()
|
||||
? m_currentCursorPosition.value() - m_lastCursorPosition.value()
|
||||
: ScreenVector(0, 0);
|
||||
|
||||
const auto cursorDelta = CursorDelta(m_currentCursorPosition, m_lastCursorPosition);
|
||||
if (m_currentCursorPosition.has_value())
|
||||
{
|
||||
m_lastCursorPosition = m_currentCursorPosition;
|
||||
@@ -192,18 +196,18 @@ namespace AzFramework
|
||||
m_idleCameraInputs.push_back(AZStd::move(cameraInput));
|
||||
}
|
||||
|
||||
bool Cameras::HandleEvents(const InputEvent& event)
|
||||
bool Cameras::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta)
|
||||
{
|
||||
bool handling = false;
|
||||
for (auto& cameraInput : m_activeCameraInputs)
|
||||
{
|
||||
cameraInput->HandleEvents(event);
|
||||
cameraInput->HandleEvents(event, cursorDelta, scrollDelta);
|
||||
handling = !cameraInput->Idle() || handling;
|
||||
}
|
||||
|
||||
for (auto& cameraInput : m_idleCameraInputs)
|
||||
{
|
||||
cameraInput->HandleEvents(event);
|
||||
cameraInput->HandleEvents(event, cursorDelta, scrollDelta);
|
||||
}
|
||||
|
||||
return handling;
|
||||
@@ -215,8 +219,8 @@ namespace AzFramework
|
||||
{
|
||||
auto& cameraInput = m_idleCameraInputs[i];
|
||||
const bool canBegin = cameraInput->Beginning() &&
|
||||
std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
|
||||
[](const auto& input) { return !input->Exclusive(); }) &&
|
||||
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
|
||||
[](const auto& input) { return !input->Exclusive(); }) &&
|
||||
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
|
||||
|
||||
if (canBegin)
|
||||
@@ -271,7 +275,7 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
void RotateCameraInput::HandleEvents(const InputEvent& event)
|
||||
void RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -279,14 +283,27 @@ namespace AzFramework
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
m_tryingToBegin = true;
|
||||
m_moveAccumulator = 0.0f;
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
m_tryingToBegin = false;
|
||||
EndActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_tryingToBegin)
|
||||
{
|
||||
// only allow the action to begin if the mouse has been moved a small amount
|
||||
m_moveAccumulator += ScreenVectorLength(cursorDelta);
|
||||
if (m_moveAccumulator > ed_cameraSystemLookDeadzone)
|
||||
{
|
||||
BeginActivation();
|
||||
m_tryingToBegin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera RotateCameraInput::StepCamera(
|
||||
@@ -298,7 +315,7 @@ namespace AzFramework
|
||||
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
|
||||
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
|
||||
|
||||
const auto clampRotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
|
||||
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
|
||||
// clamp pitch to be +-90 degrees
|
||||
@@ -307,7 +324,8 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void PanCameraInput::HandleEvents(const InputEvent& event)
|
||||
void PanCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -382,7 +400,8 @@ namespace AzFramework
|
||||
return TranslationType::Nil;
|
||||
}
|
||||
|
||||
void TranslateCameraInput::HandleEvents(const InputEvent& event)
|
||||
void TranslateCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -478,7 +497,7 @@ namespace AzFramework
|
||||
m_boost = false;
|
||||
}
|
||||
|
||||
void OrbitCameraInput::HandleEvents(const InputEvent& event)
|
||||
void OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta)
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -497,7 +516,7 @@ namespace AzFramework
|
||||
|
||||
if (Active())
|
||||
{
|
||||
m_orbitCameras.HandleEvents(event);
|
||||
m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,8 +528,10 @@ namespace AzFramework
|
||||
if (Beginning())
|
||||
{
|
||||
float hit_distance = 0.0f;
|
||||
if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight))
|
||||
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance))
|
||||
AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight))
|
||||
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance);
|
||||
|
||||
if (hit_distance > 0.0f)
|
||||
{
|
||||
hit_distance = AZStd::min<float>(hit_distance, ed_cameraSystemMaxOrbitDistance);
|
||||
nextCamera.m_lookDist = -hit_distance;
|
||||
@@ -539,7 +560,8 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitDollyScrollCameraInput::HandleEvents(const InputEvent& event)
|
||||
void OrbitDollyScrollCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
@@ -557,7 +579,8 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void OrbitDollyCursorMoveCameraInput::HandleEvents(const InputEvent& event)
|
||||
void OrbitDollyCursorMoveCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
@@ -584,7 +607,8 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void ScrollTranslationCameraInput::HandleEvents(const InputEvent& event)
|
||||
void ScrollTranslationCameraInput::HandleEvents(
|
||||
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
|
||||
{
|
||||
@@ -610,7 +634,7 @@ namespace AzFramework
|
||||
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime)
|
||||
{
|
||||
const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
|
||||
// keep yaw in 0 - 360 range
|
||||
float targetYaw = clamp_rotation(targetCamera.m_yaw);
|
||||
@@ -621,7 +645,7 @@ namespace AzFramework
|
||||
|
||||
// ensure smooth transition when moving across 0 - 360 boundary
|
||||
const float yawDelta = targetYaw - currentYaw;
|
||||
if (std::abs(yawDelta) >= AZ::Constants::Pi)
|
||||
if (AZStd::abs(yawDelta) >= AZ::Constants::Pi)
|
||||
{
|
||||
targetYaw -= AZ::Constants::TwoPi * sign(yawDelta);
|
||||
}
|
||||
@@ -629,12 +653,12 @@ namespace AzFramework
|
||||
Camera camera;
|
||||
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
|
||||
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
|
||||
const float lookRate = std::exp2(ed_cameraSystemLookSmoothness);
|
||||
const float lookT = std::exp2(-lookRate * deltaTime);
|
||||
const float lookRate = AZStd::exp2(ed_cameraSystemLookSmoothness);
|
||||
const float lookT = AZStd::exp2(-lookRate * deltaTime);
|
||||
camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT);
|
||||
camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookT);
|
||||
const float moveRate = std::exp2(ed_cameraSystemTranslateSmoothness);
|
||||
const float moveT = std::exp2(-moveRate * deltaTime);
|
||||
const float moveRate = AZStd::exp2(ed_cameraSystemTranslateSmoothness);
|
||||
const float moveT = AZStd::exp2(-moveRate * deltaTime);
|
||||
camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT);
|
||||
camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveT);
|
||||
return camera;
|
||||
@@ -655,7 +679,7 @@ namespace AzFramework
|
||||
const auto* position = inputChannel.GetCustomData<AzFramework::InputChannel::PositionData2D>();
|
||||
AZ_Assert(position, "Expected PositionData2D but found nullptr");
|
||||
|
||||
return CursorMotionEvent{ScreenPoint(
|
||||
return CursorEvent{ScreenPoint(
|
||||
position->m_normalizedPosition.GetX() * windowSize.m_width, position->m_normalizedPosition.GetY() * windowSize.m_height)};
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Z)
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace AzFramework
|
||||
|
||||
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform);
|
||||
|
||||
struct CursorMotionEvent
|
||||
struct CursorEvent
|
||||
{
|
||||
ScreenPoint m_position;
|
||||
};
|
||||
@@ -86,7 +86,7 @@ namespace AzFramework
|
||||
InputChannel::State m_state; //!< Channel state. (e.g. Begin/update/end event).
|
||||
};
|
||||
|
||||
using InputEvent = AZStd::variant<AZStd::monostate, CursorMotionEvent, ScrollEvent, DiscreteInputEvent>;
|
||||
using InputEvent = AZStd::variant<AZStd::monostate, CursorEvent, ScrollEvent, DiscreteInputEvent>;
|
||||
|
||||
class CameraInput
|
||||
{
|
||||
@@ -147,7 +147,7 @@ namespace AzFramework
|
||||
ResetImpl();
|
||||
}
|
||||
|
||||
virtual void HandleEvents(const InputEvent& event) = 0;
|
||||
virtual void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) = 0;
|
||||
virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0;
|
||||
|
||||
virtual bool Exclusive() const
|
||||
@@ -170,7 +170,7 @@ namespace AzFramework
|
||||
{
|
||||
public:
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
bool HandleEvents(const InputEvent& event);
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta);
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
|
||||
void Reset();
|
||||
|
||||
@@ -201,11 +201,13 @@ namespace AzFramework
|
||||
{
|
||||
}
|
||||
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
InputChannelId m_rotateChannelId;
|
||||
float m_moveAccumulator = 0.0f;
|
||||
bool m_tryingToBegin = false;
|
||||
};
|
||||
|
||||
struct PanAxes
|
||||
@@ -243,7 +245,7 @@ namespace AzFramework
|
||||
, m_panChannelId(panChannelId)
|
||||
{
|
||||
}
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
@@ -285,7 +287,7 @@ namespace AzFramework
|
||||
: m_translationAxesFn(AZStd::move(translationAxesFn))
|
||||
{
|
||||
}
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
void ResetImpl() override;
|
||||
|
||||
@@ -354,7 +356,7 @@ namespace AzFramework
|
||||
class OrbitDollyScrollCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
};
|
||||
|
||||
@@ -364,7 +366,7 @@ namespace AzFramework
|
||||
explicit OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId)
|
||||
: m_dollyChannelId(dollyChannelId) {}
|
||||
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
|
||||
private:
|
||||
@@ -374,14 +376,14 @@ namespace AzFramework
|
||||
class ScrollTranslationCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
};
|
||||
|
||||
class OrbitCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event) override;
|
||||
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
|
||||
bool Exclusive() const override
|
||||
{
|
||||
|
||||
@@ -134,11 +134,16 @@ namespace AzFramework
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
inline float ScreenVectorLength(const ScreenVector& screenVector)
|
||||
{
|
||||
return aznumeric_cast<float>(AZStd::sqrt(screenVector.m_x * screenVector.m_x + screenVector.m_y * screenVector.m_y));
|
||||
}
|
||||
|
||||
inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize)
|
||||
{
|
||||
return ScreenPoint(
|
||||
aznumeric_caster(std::round(screenNDC.GetX() * viewportSize.GetX())),
|
||||
aznumeric_caster(std::round((1.0f - screenNDC.GetY()) * viewportSize.GetY())));
|
||||
aznumeric_caster(AZStd::round(screenNDC.GetX() * viewportSize.GetX())),
|
||||
aznumeric_caster(AZStd::round((1.0f - screenNDC.GetY()) * viewportSize.GetY())));
|
||||
}
|
||||
|
||||
inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize)
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace AzToolsFramework
|
||||
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
|
||||
{
|
||||
return AZ::Failure(
|
||||
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
|
||||
AZStd::string("Could not create a new prefab out of the entities provided - invalid selection."));
|
||||
}
|
||||
|
||||
// When we create a prefab with other prefab instances, we have to remove the existing links between the source and
|
||||
@@ -140,9 +140,13 @@ namespace AzToolsFramework
|
||||
// Mark them as dirty so this change is correctly applied to the template
|
||||
for (AZ::Entity* topLevelEntity : topLevelEntities)
|
||||
{
|
||||
m_prefabUndoCache.UpdateCache(topLevelEntity->GetId());
|
||||
undoBatch.MarkEntityDirty(topLevelEntity->GetId());
|
||||
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
|
||||
AZ::EntityId topLevelEntityId = topLevelEntity->GetId();
|
||||
if (topLevelEntityId.IsValid())
|
||||
{
|
||||
m_prefabUndoCache.UpdateCache(topLevelEntityId);
|
||||
undoBatch.MarkEntityDirty(topLevelEntityId);
|
||||
AZ::TransformBus::Event(topLevelEntityId, &AZ::TransformBus::Events::SetParent, containerEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
// Select Container Entity
|
||||
@@ -237,6 +241,21 @@ namespace AzToolsFramework
|
||||
// Retrieve entityList from entityIds
|
||||
inputEntityList = EntityIdListToEntityList(entityIds);
|
||||
|
||||
// Remove Level Container Entity if it's part of the list
|
||||
AZ::EntityId levelEntityId = GetLevelInstanceContainerEntityId();
|
||||
if (levelEntityId.IsValid())
|
||||
{
|
||||
AZ::Entity* levelEntity = GetEntityById(levelEntityId);
|
||||
if (levelEntity)
|
||||
{
|
||||
auto levelEntityIter = AZStd::find(inputEntityList.begin(), inputEntityList.end(), levelEntity);
|
||||
if (levelEntityIter != inputEntityList.end())
|
||||
{
|
||||
inputEntityList.erase(levelEntityIter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find common root and top level entities
|
||||
bool entitiesHaveCommonRoot = false;
|
||||
|
||||
@@ -807,6 +826,11 @@ namespace AzToolsFramework
|
||||
const EntityList& inputEntities, Instance& commonRootEntityOwningInstance,
|
||||
EntityList& outEntities, AZStd::vector<AZStd::unique_ptr<Instance>>& outInstances) const
|
||||
{
|
||||
if (inputEntities.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::queue<AZ::Entity*> entityQueue;
|
||||
|
||||
for (auto inputEntity : inputEntities)
|
||||
@@ -894,7 +918,7 @@ namespace AzToolsFramework
|
||||
outInstances.push_back(AZStd::move(commonRootEntityOwningInstance.DetachNestedInstance(instancePtr->GetInstanceAlias())));
|
||||
}
|
||||
|
||||
return true;
|
||||
return (outEntities.size() + outInstances.size()) > 0;
|
||||
}
|
||||
|
||||
bool PrefabPublicHandler::EntitiesBelongToSameInstance(const EntityIdList& entityIds) const
|
||||
|
||||
@@ -1353,7 +1353,7 @@ namespace AzToolsFramework
|
||||
// Iterate over the entities left in the instance and if none of them have this
|
||||
// asset entity as its ancestor, then we want to remove it.
|
||||
// \todo - Investigate ways to make this non-linear time. Tricky since removed entities
|
||||
// obviously aren't maintained in any maps. (https://jira.agscollab.com/browse/LY-88218)
|
||||
// obviously aren't maintained in any maps. (LY-88218)
|
||||
bool foundAsAncestor = false;
|
||||
for (const AZ::Entity* instanceEntity : instanceEntities)
|
||||
{
|
||||
|
||||
+32
-19
@@ -151,32 +151,36 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (!selectedEntities.empty())
|
||||
{
|
||||
bool layerInSelection = false;
|
||||
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
// Hide if the only selected entity is the Level Container
|
||||
if (selectedEntities.size() > 1 || !s_prefabPublicInterface->IsLevelInstanceContainerEntity(selectedEntities[0]))
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection, entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
bool layerInSelection = false;
|
||||
|
||||
if (layerInSelection)
|
||||
for (AZ::EntityId entityId : selectedEntities)
|
||||
{
|
||||
if (!layerInSelection)
|
||||
{
|
||||
break;
|
||||
AzToolsFramework::Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
layerInSelection, entityId,
|
||||
&AzToolsFramework::Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
|
||||
if (layerInSelection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
// Layers can't be in prefabs.
|
||||
if (!layerInSelection)
|
||||
{
|
||||
QAction* createAction = menu->addAction(QObject::tr("Create Prefab..."));
|
||||
createAction->setToolTip(QObject::tr("Creates a prefab out of the currently selected entities."));
|
||||
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
QObject::connect(createAction, &QAction::triggered, createAction, [this, selectedEntities] {
|
||||
ContextMenu_CreatePrefab(selectedEntities);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,6 +276,15 @@ namespace AzToolsFramework
|
||||
QWidget* activeWindow = QApplication::activeWindow();
|
||||
const AZStd::string prefabFilesPath = "@devassets@/Prefabs";
|
||||
|
||||
// Remove Level entity if it's part of the list
|
||||
|
||||
auto levelContainerIter =
|
||||
AZStd::find(selectedEntities.begin(), selectedEntities.end(), s_prefabPublicInterface->GetLevelInstanceContainerEntityId());
|
||||
if (levelContainerIter != selectedEntities.end())
|
||||
{
|
||||
selectedEntities.erase(levelContainerIter);
|
||||
}
|
||||
|
||||
// Set default folder for prefabs
|
||||
AZ::IO::FileIOBase* fileIoBaseInstance = AZ::IO::FileIOBase::GetInstance();
|
||||
|
||||
|
||||
@@ -211,6 +211,15 @@ namespace UnitTest
|
||||
EXPECT_EQ(screenPoint, ScreenPoint(45, 170));
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, ScreenVectorLengthReturned)
|
||||
{
|
||||
using AzFramework::ScreenVector;
|
||||
|
||||
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(1, 1)), 1.41421f, 0.001f);
|
||||
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(3, 4)), 5.0f, 0.001f);
|
||||
EXPECT_NEAR(AzFramework::ScreenVectorLength(ScreenVector(12, 15)), 19.20937f, 0.001f);
|
||||
}
|
||||
|
||||
TEST(ViewportScreen, CanGetCameraTransformFromCameraViewAndBack)
|
||||
{
|
||||
const auto screenDimensions = AZ::Vector2(1024.0f, 768.0f);
|
||||
|
||||
@@ -660,9 +660,7 @@ void Q2DViewport::Draw(DisplayContext& dc)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers)
|
||||
{
|
||||
CGrid* pGrid = GetIEditor()->GetViewManager()->GetGrid();
|
||||
float gridSize = pGrid->size;
|
||||
|
||||
float gridSize = 1.0f;
|
||||
if (gridSize < 0.00001f)
|
||||
{
|
||||
return;
|
||||
@@ -693,8 +691,6 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers)
|
||||
pixelsPerGrid = gridSize * fScale;
|
||||
while (pixelsPerGrid <= 5 && griditers++ < 20)
|
||||
{
|
||||
m_fGridZoom *= pGrid->majorLine;
|
||||
gridSize = gridSize * pGrid->majorLine;
|
||||
pixelsPerGrid = gridSize * fScale;
|
||||
}
|
||||
}
|
||||
@@ -743,7 +739,7 @@ void Q2DViewport::DrawGrid(DisplayContext& dc, bool bNoXNumbers)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw Major grid lines.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
gridSize = gridSize * pGrid->majorLine;
|
||||
gridSize = gridSize * 1.0f;
|
||||
|
||||
if (m_bAutoAdjustGrids)
|
||||
{
|
||||
|
||||
@@ -514,7 +514,7 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
|
||||
/*
|
||||
* The following block of code is part of the feature "Isolation Mode" and is temporarily
|
||||
* disabled for 1.10 release.
|
||||
* Jira: https://jira.agscollab.com/browse/LY-49532
|
||||
* Jira: LY-49532
|
||||
|
||||
// Isolate Selected
|
||||
QAction* isolateSelectedAction = editMenu->addAction(tr("Isolate Selected"));
|
||||
@@ -729,9 +729,6 @@ QMenu* LevelEditorMenuHandler::CreateViewMenu()
|
||||
viewportViewsMenuWrapper.AddAction(ID_WIREFRAME);
|
||||
viewportViewsMenuWrapper.AddSeparator();
|
||||
|
||||
viewportViewsMenuWrapper.AddAction(ID_VIEW_GRIDSETTINGS);
|
||||
viewportViewsMenuWrapper.AddSeparator();
|
||||
|
||||
if (CViewManager::IsMultiViewportEnabled())
|
||||
{
|
||||
viewportViewsMenuWrapper.AddAction(ID_VIEW_CONFIGURELAYOUT);
|
||||
|
||||
@@ -95,7 +95,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "Core/QtEditorApplication.h"
|
||||
#include "StringDlg.h"
|
||||
#include "NewLevelDialog.h"
|
||||
#include "GridSettingsDialog.h"
|
||||
#include "LayoutConfigDialog.h"
|
||||
#include "ViewManager.h"
|
||||
#include "FileTypeUtils.h"
|
||||
@@ -400,7 +399,6 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
|
||||
ON_COMMAND(ID_WIREFRAME, OnWireframe)
|
||||
|
||||
ON_COMMAND(ID_VIEW_GRIDSETTINGS, OnViewGridsettings)
|
||||
ON_COMMAND(ID_VIEW_CONFIGURELAYOUT, OnViewConfigureLayout)
|
||||
|
||||
ON_COMMAND(IDC_SELECTION, OnDummyCommand)
|
||||
@@ -3459,14 +3457,6 @@ void CCryEditApp::OnUpdateWireframe(QAction* action)
|
||||
action->setChecked(nWireframe == R_WIREFRAME_MODE);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnViewGridsettings()
|
||||
{
|
||||
CGridSettingsDialog dlg;
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnViewConfigureLayout()
|
||||
{
|
||||
|
||||
@@ -366,7 +366,6 @@ private:
|
||||
|
||||
void OnWireframe();
|
||||
void OnUpdateWireframe(QAction* action);
|
||||
void OnViewGridsettings();
|
||||
void OnViewConfigureLayout();
|
||||
|
||||
// Tag Locations.
|
||||
|
||||
@@ -579,23 +579,13 @@ void CCryEditDoc::SerializeViewSettings(CXmlArchive& xmlAr)
|
||||
view->getAttr(viewerAnglesName.toUtf8().constData(), va);
|
||||
}
|
||||
|
||||
CViewport* pVP = GetIEditor()->GetViewManager()->GetView(i);
|
||||
Matrix34 tm = Matrix34::CreateRotationXYZ(va);
|
||||
tm.SetTranslation(vp);
|
||||
|
||||
|
||||
if (pVP)
|
||||
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
|
||||
if (auto viewportContext = viewportContextManager->GetViewportContextById(i))
|
||||
{
|
||||
Matrix34 tm = Matrix34::CreateRotationXYZ(va);
|
||||
tm.SetTranslation(vp);
|
||||
pVP->SetViewTM(tm);
|
||||
}
|
||||
|
||||
// Load grid.
|
||||
auto gridName = QString("Grid%1").arg(useOldViewFormat ? "" : QString::number(i));
|
||||
XmlNodeRef gridNode = xmlAr.root->newChild(gridName.toUtf8().constData());
|
||||
|
||||
if (gridNode)
|
||||
{
|
||||
GetIEditor()->GetViewManager()->GetGrid()->Serialize(gridNode, xmlAr.bLoading);
|
||||
viewportContext->SetCameraTransform(LYTransformToAZTransform(tm));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -622,11 +612,6 @@ void CCryEditDoc::SerializeViewSettings(CXmlArchive& xmlAr)
|
||||
auto viewerAnglesName = QString("ViewerAngles%1").arg(i);
|
||||
view->setAttr(viewerAnglesName.toUtf8().constData(), angles);
|
||||
}
|
||||
|
||||
// Save grid.
|
||||
auto gridName = QString("Grid%1").arg(i);
|
||||
XmlNodeRef gridNode = xmlAr.root->newChild(gridName.toUtf8().constData());
|
||||
GetIEditor()->GetViewManager()->GetGrid()->Serialize(gridNode, xmlAr.bLoading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,8 +453,11 @@ void EditorViewportWidget::Update()
|
||||
}
|
||||
|
||||
m_updatingCameraPosition = true;
|
||||
auto transform = LYTransformToAZTransform(m_Camera.GetMatrix());
|
||||
m_renderViewport->GetViewportContext()->SetCameraTransform(transform);
|
||||
if (!ed_useNewCameraSystem)
|
||||
{
|
||||
m_renderViewport->GetViewportContext()->SetCameraTransform(LYTransformToAZTransform(m_Camera.GetMatrix()));
|
||||
}
|
||||
|
||||
AZ::Matrix4x4 clipMatrix;
|
||||
AZ::MakePerspectiveFovMatrixRH(
|
||||
clipMatrix,
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Grid.h"
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CGrid::CGrid()
|
||||
{
|
||||
scale = 1;
|
||||
size = 1;
|
||||
majorLine = 16;
|
||||
bEnabled = true;
|
||||
rotationAngles = Ang3(0.0f, 0.0f, 0.0f);
|
||||
translation = Vec3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
bAngleSnapEnabled = true;
|
||||
angleSnap = 5;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 CGrid::Snap(const Vec3& vec) const
|
||||
{
|
||||
if (!bEnabled || size < 0.001)
|
||||
{
|
||||
return vec;
|
||||
}
|
||||
Vec3 snapped;
|
||||
snapped.x = floor((vec.x / size) / scale + 0.5) * size * scale;
|
||||
snapped.y = floor((vec.y / size) / scale + 0.5) * size * scale;
|
||||
snapped.z = floor((vec.z / size) / scale + 0.5) * size * scale;
|
||||
return snapped;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 CGrid::Snap(const Vec3& vec, double fZoom) const
|
||||
{
|
||||
if (!bEnabled || size < 0.001f)
|
||||
{
|
||||
return vec;
|
||||
}
|
||||
|
||||
Matrix34 tm = GetMatrix();
|
||||
|
||||
double zoomscale = scale * fZoom;
|
||||
Vec3 snapped;
|
||||
|
||||
Matrix34 invtm = tm.GetInverted();
|
||||
|
||||
snapped = invtm * vec;
|
||||
|
||||
snapped.x = floor((snapped.x / size) / zoomscale + 0.5) * size * zoomscale;
|
||||
snapped.y = floor((snapped.y / size) / zoomscale + 0.5) * size * zoomscale;
|
||||
snapped.z = floor((snapped.z / size) / zoomscale + 0.5) * size * zoomscale;
|
||||
|
||||
snapped = tm * snapped;
|
||||
|
||||
return snapped;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
double CGrid::SnapAngle(double angle) const
|
||||
{
|
||||
if (!bAngleSnapEnabled)
|
||||
{
|
||||
return angle;
|
||||
}
|
||||
return floor(angle / angleSnap + 0.5) * angleSnap;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Ang3 CGrid::SnapAngle(const Ang3& vec) const
|
||||
{
|
||||
if (!bAngleSnapEnabled)
|
||||
{
|
||||
return vec;
|
||||
}
|
||||
Ang3 snapped;
|
||||
snapped.x = floor(vec.x / angleSnap + 0.5) * angleSnap;
|
||||
snapped.y = floor(vec.y / angleSnap + 0.5) * angleSnap;
|
||||
snapped.z = floor(vec.z / angleSnap + 0.5) * angleSnap;
|
||||
return snapped;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGrid::Serialize(XmlNodeRef& xmlNode, bool bLoading)
|
||||
{
|
||||
if (bLoading)
|
||||
{
|
||||
// Loading.
|
||||
xmlNode->getAttr("Size", size);
|
||||
xmlNode->getAttr("Scale", scale);
|
||||
xmlNode->getAttr("Enabled", bEnabled);
|
||||
xmlNode->getAttr("MajorSize", majorLine);
|
||||
xmlNode->getAttr("AngleSnap", angleSnap);
|
||||
xmlNode->getAttr("AngleSnapEnabled", bAngleSnapEnabled);
|
||||
if (size < 0.01)
|
||||
{
|
||||
size = 0.01;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Saving.
|
||||
xmlNode->setAttr("Size", size);
|
||||
xmlNode->setAttr("Scale", scale);
|
||||
xmlNode->setAttr("Enabled", bEnabled);
|
||||
xmlNode->setAttr("MajorSize", majorLine);
|
||||
xmlNode->setAttr("AngleSnap", angleSnap);
|
||||
xmlNode->setAttr("AngleSnapEnabled", bAngleSnapEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Matrix34 CGrid::GetMatrix() const
|
||||
{
|
||||
Matrix34 tm;
|
||||
|
||||
if (gSettings.snap.bGridUserDefined)
|
||||
{
|
||||
Ang3 angles = Ang3(rotationAngles.x * gf_PI / 180.0, rotationAngles.y * gf_PI / 180.0, rotationAngles.z * gf_PI / 180.0);
|
||||
|
||||
tm = Matrix33::CreateRotationXYZ(angles);
|
||||
}
|
||||
else if (GetIEditor()->GetReferenceCoordSys() == COORDS_LOCAL)
|
||||
{
|
||||
tm.SetIdentity();
|
||||
}
|
||||
else
|
||||
{
|
||||
tm.SetIdentity();
|
||||
}
|
||||
|
||||
return tm;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_GRID_H
|
||||
#define CRYINCLUDE_EDITOR_GRID_H
|
||||
|
||||
#pragma once
|
||||
|
||||
/** Definition of grid used in 2D viewports.
|
||||
*/
|
||||
class SANDBOX_API CGrid
|
||||
{
|
||||
public:
|
||||
//! Resolution of grid, it must be multiply of 2.
|
||||
double size;
|
||||
//! Draw major lines every Nth grid line.
|
||||
int majorLine;
|
||||
//! True if grid enabled.
|
||||
bool bEnabled;
|
||||
//! Meters per grid unit.
|
||||
double scale;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Ang3 rotationAngles;
|
||||
Vec3 translation;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
//! If snap to angle.
|
||||
bool bAngleSnapEnabled;
|
||||
double angleSnap;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CGrid();
|
||||
|
||||
//! Snap vector to this grid.
|
||||
Vec3 Snap(const Vec3& vec) const;
|
||||
Vec3 Snap(const Vec3& vec, double fZoom) const;
|
||||
|
||||
//! Snap angle to current angle snapping value.
|
||||
double SnapAngle(double angle) const;
|
||||
//! Snap angle to current angle snapping value.
|
||||
Ang3 SnapAngle(const Ang3& angle) const;
|
||||
|
||||
//! Enable or disable grid.
|
||||
void Enable(bool enable) { bEnabled = enable; }
|
||||
//! Check if grid enabled.
|
||||
bool IsEnabled() const { return bEnabled; }
|
||||
|
||||
//! Enables or disable angle snapping.
|
||||
void EnableAngleSnap(bool enable) { bAngleSnapEnabled = enable; };
|
||||
|
||||
//! Return if snapping of angle is enabled.
|
||||
bool IsAngleSnapEnabled() const { return bAngleSnapEnabled; };
|
||||
//! Returns ammount of snapping for angle in degrees.
|
||||
double GetAngleSnap() const { return angleSnap; };
|
||||
|
||||
void Serialize(XmlNodeRef& xmlNode, bool bLoading);
|
||||
|
||||
//! Get transformation matrix of gird.
|
||||
Matrix34 GetMatrix() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_GRID_H
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "GridSettingsDialog.h"
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
#include "ViewManager.h"
|
||||
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <ui_GridSettingsDialog.h>
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
// CGridSettingsDialog dialog
|
||||
|
||||
CGridSettingsDialog::CGridSettingsDialog(QWidget* pParent /*=NULL*/)
|
||||
: QDialog(pParent)
|
||||
, ui(new Ui::CGridSettingsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowTitle(tr("Grid/Snap Settings"));
|
||||
|
||||
OnInitDialog();
|
||||
|
||||
connect(ui->m_userDefined, &QCheckBox::clicked, this, &CGridSettingsDialog::OnBnUserDefined);
|
||||
connect(ui->m_getFromObject, &QCheckBox::clicked, this, &CGridSettingsDialog::OnBnGetFromObject);
|
||||
|
||||
auto doubleSpinBoxValueChanged = static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
|
||||
|
||||
connect(ui->m_angleX, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
connect(ui->m_angleY, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
connect(ui->m_angleZ, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
|
||||
connect(ui->m_gridSize, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
connect(ui->m_gridScale, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
connect(ui->m_CPSize, doubleSpinBoxValueChanged, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
|
||||
connect(ui->m_displayCP, &QCheckBox::clicked, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
connect(ui->m_getFromObject, &QCheckBox::clicked, this, &CGridSettingsDialog::OnValueUpdate);
|
||||
|
||||
connect(ui->m_buttonBox, &QDialogButtonBox::accepted, this, &CGridSettingsDialog::accept);
|
||||
connect(ui->m_buttonBox, &QDialogButtonBox::rejected, this, &CGridSettingsDialog::reject);
|
||||
}
|
||||
|
||||
CGridSettingsDialog::~CGridSettingsDialog()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGridSettingsDialog::OnInitDialog()
|
||||
{
|
||||
CGrid* pGrid = GetIEditor()->GetViewManager()->GetGrid();
|
||||
|
||||
ui->m_userDefined->setChecked(gSettings.snap.bGridUserDefined);
|
||||
ui->m_getFromObject->setChecked(gSettings.snap.bGridGetFromSelected);
|
||||
|
||||
ui->m_angleX->setValue(pGrid->rotationAngles.x);
|
||||
ui->m_angleY->setValue(pGrid->rotationAngles.y);
|
||||
ui->m_angleZ->setValue(pGrid->rotationAngles.z);
|
||||
|
||||
ui->m_translationX->setValue(pGrid->translation.x);
|
||||
ui->m_translationY->setValue(pGrid->translation.y);
|
||||
ui->m_translationZ->setValue(pGrid->translation.z);
|
||||
|
||||
ui->m_gridSize->setValue(pGrid->size);
|
||||
ui->m_gridScale->setValue(pGrid->scale);
|
||||
ui->m_snapToGrid->setChecked(pGrid->IsEnabled());
|
||||
|
||||
ui->m_angleSnap->setChecked(pGrid->IsAngleSnapEnabled());
|
||||
ui->m_angleSnapScale->setValue(pGrid->GetAngleSnap());
|
||||
ui->m_displayCP->setChecked(gSettings.snap.constructPlaneDisplay);
|
||||
|
||||
ui->m_CPSize->setValue(gSettings.snap.constructPlaneSize);
|
||||
ui->m_displaySnapMarker->setChecked(gSettings.snap.markerDisplay);
|
||||
ui->m_snapMarkerSize->setValue(gSettings.snap.markerSize);
|
||||
|
||||
ui->m_snapMarkerColor->SetColor(gSettings.snap.markerColor);
|
||||
|
||||
EnableGridPropertyControls(gSettings.snap.bGridUserDefined, gSettings.snap.bGridGetFromSelected);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGridSettingsDialog::accept()
|
||||
{
|
||||
UpdateValues();
|
||||
gSettings.Save();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void CGridSettingsDialog::OnBnUserDefined()
|
||||
{
|
||||
EnableGridPropertyControls(ui->m_userDefined->isChecked(), ui->m_getFromObject->isChecked());
|
||||
OnValueUpdate();
|
||||
}
|
||||
|
||||
void CGridSettingsDialog::OnBnGetFromObject()
|
||||
{
|
||||
EnableGridPropertyControls(ui->m_userDefined->isChecked(), ui->m_getFromObject->isChecked());
|
||||
}
|
||||
|
||||
void CGridSettingsDialog::EnableGridPropertyControls(const bool isUserDefined, const bool isGetFromObject)
|
||||
{
|
||||
ui->m_getFromObject->setEnabled(isUserDefined == true);
|
||||
|
||||
ui->m_angleX->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_angleY->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_angleZ->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_translationX->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_translationY->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_translationZ->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_getAnglesFromObject->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
ui->m_getTranslationFromObject->setEnabled(isUserDefined == true && isGetFromObject == false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGridSettingsDialog::UpdateValues()
|
||||
{
|
||||
CGrid* pGrid = GetIEditor()->GetViewManager()->GetGrid();
|
||||
|
||||
pGrid->Enable(ui->m_snapToGrid->isChecked());
|
||||
pGrid->size = ui->m_gridSize->value();
|
||||
pGrid->scale = ui->m_gridScale->value();
|
||||
|
||||
gSettings.snap.bGridUserDefined = ui->m_userDefined->isChecked();
|
||||
gSettings.snap.bGridGetFromSelected = ui->m_getFromObject->isChecked();
|
||||
pGrid->rotationAngles.x = ui->m_angleX->value();
|
||||
pGrid->rotationAngles.y = ui->m_angleY->value();
|
||||
pGrid->rotationAngles.z = ui->m_angleZ->value();
|
||||
pGrid->translation.x = ui->m_translationX->value();
|
||||
pGrid->translation.y = ui->m_translationY->value();
|
||||
pGrid->translation.z = ui->m_translationZ->value();
|
||||
|
||||
pGrid->bAngleSnapEnabled = ui->m_angleSnap->isChecked();
|
||||
pGrid->angleSnap = ui->m_angleSnapScale->value();
|
||||
|
||||
gSettings.snap.constructPlaneDisplay = ui->m_displayCP->isChecked();
|
||||
gSettings.snap.constructPlaneSize = ui->m_CPSize->value();
|
||||
|
||||
gSettings.snap.markerDisplay = ui->m_displaySnapMarker->isChecked();
|
||||
gSettings.snap.markerSize = ui->m_snapMarkerSize->value();
|
||||
gSettings.snap.markerColor = ui->m_snapMarkerColor->Color();
|
||||
|
||||
NotificationBus::Broadcast(&Notifications::OnGridValuesUpdated);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGridSettingsDialog::OnValueUpdate()
|
||||
{
|
||||
UpdateValues();
|
||||
GetIEditor()->UpdateViews(eRedrawViewports);
|
||||
}
|
||||
|
||||
#include <moc_GridSettingsDialog.cpp>
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_GRIDSETTINGSDIALOG_H
|
||||
#define CRYINCLUDE_EDITOR_GRIDSETTINGSDIALOG_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#endif
|
||||
|
||||
// CGridSettingsDialog dialog
|
||||
|
||||
namespace Ui {
|
||||
class CGridSettingsDialog;
|
||||
}
|
||||
|
||||
class CGridSettingsDialog
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
class Notifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
virtual void OnGridValuesUpdated() {}
|
||||
};
|
||||
|
||||
using NotificationBus = AZ::EBus<Notifications>;
|
||||
|
||||
CGridSettingsDialog(QWidget* pParent = nullptr); // standard constructor
|
||||
virtual ~CGridSettingsDialog();
|
||||
|
||||
private slots:
|
||||
void accept() override;
|
||||
void OnBnUserDefined();
|
||||
void OnBnGetFromObject();
|
||||
void OnValueUpdate();
|
||||
|
||||
private:
|
||||
void EnableGridPropertyControls(const bool isUserDefined, const bool isGetFromObject);
|
||||
|
||||
void OnInitDialog();
|
||||
void UpdateValues();
|
||||
|
||||
QScopedPointer<Ui::CGridSettingsDialog> ui;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_GRIDSETTINGSDIALOG_H
|
||||
@@ -1,505 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CGridSettingsDialog</class>
|
||||
<widget class="QDialog" name="CGridSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>307</width>
|
||||
<height>707</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="group1">
|
||||
<property name="title">
|
||||
<string>Grid</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="m_snapToGrid">
|
||||
<property name="text">
|
||||
<string>Snap to Grid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label1">
|
||||
<property name="text">
|
||||
<string>Grid Lines Every:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_gridSize">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1024.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label2">
|
||||
<property name="text">
|
||||
<string>units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label3">
|
||||
<property name="text">
|
||||
<string>Units Per Meter:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_gridScale">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1024.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="label4">
|
||||
<property name="text">
|
||||
<string>meters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="m_userDefined">
|
||||
<property name="text">
|
||||
<string>User Defined Grid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="m_getFromObject">
|
||||
<property name="text">
|
||||
<string>Get Angles And Trans. From Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label5">
|
||||
<property name="text">
|
||||
<string>Rotation by X:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_angleX">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label6">
|
||||
<property name="text">
|
||||
<string>degrees</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label7">
|
||||
<property name="text">
|
||||
<string>Rotation by Y:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_angleY">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="label8">
|
||||
<property name="text">
|
||||
<string>degrees</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label9">
|
||||
<property name="text">
|
||||
<string>Rotation by Z:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_angleZ">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="label10">
|
||||
<property name="text">
|
||||
<string>degrees</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label11">
|
||||
<property name="text">
|
||||
<string>Translation by X:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_translationX">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label12">
|
||||
<property name="text">
|
||||
<string>Translation by Y:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_translationY">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label13">
|
||||
<property name="text">
|
||||
<string>Translation by Z:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_translationZ">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="3">
|
||||
<widget class="QPushButton" name="m_getAnglesFromObject">
|
||||
<property name="text">
|
||||
<string>Get Angles From Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="3">
|
||||
<widget class="QPushButton" name="m_getTranslationFromObject">
|
||||
<property name="text">
|
||||
<string>Get Translation From Selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="group2">
|
||||
<property name="title">
|
||||
<string>Angle Snapping</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="m_angleSnapScale">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label14">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>degrees</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QCheckBox" name="m_angleSnap">
|
||||
<property name="text">
|
||||
<string>Angle Snap</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label15">
|
||||
<property name="text">
|
||||
<string>Angle Snap:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="group3">
|
||||
<property name="title">
|
||||
<string>Construction Plane</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label16">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="m_displayCP">
|
||||
<property name="text">
|
||||
<string>Display</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QDoubleSpinBox" name="m_CPSize">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>m_displayCP</zorder>
|
||||
<zorder>m_CPSize</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="group4">
|
||||
<property name="title">
|
||||
<string>Snap Marker</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="3">
|
||||
<widget class="QDoubleSpinBox" name="m_snapMarkerSize">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="m_displaySnapMarker">
|
||||
<property name="text">
|
||||
<string>Display</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="ColorButton" name="m_snapMarkerColor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label17">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="m_buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ColorButton</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header location="global">QtUI/ColorButton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -66,7 +66,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "AssetImporter/AssetImporterManager/AssetImporterDragAndDropHandler.h"
|
||||
#include "CryEdit.h"
|
||||
#include "Controls/ConsoleSCB.h"
|
||||
#include "Grid.h"
|
||||
#include "ViewManager.h"
|
||||
#include "CryEditDoc.h"
|
||||
#include "ToolBox.h"
|
||||
@@ -97,7 +96,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
#include "AzAssetBrowser/AzAssetBrowserWindow.h"
|
||||
#include "AssetEditor/AssetEditorWindow.h"
|
||||
#include "GridSettingsDialog.h"
|
||||
#include "ActionManager.h"
|
||||
|
||||
// uncomment this to show thumbnail demo widget
|
||||
@@ -123,12 +121,6 @@ static const char* g_openLocationAttributeName = "OpenLocation"; //Indicates whe
|
||||
|
||||
static const char* g_assetImporterName = "AssetImporter";
|
||||
|
||||
static const char* g_snapToGridEnabled = "mainwindow/snapGridEnabled";
|
||||
static const char* g_snapToGridSize = "mainwindow/snapGridSize";
|
||||
static const char* g_snapAngleEnabled = "mainwindow/snapAngleEnabled";
|
||||
static const char* g_snapAngle = "mainwindow/snapAngle";
|
||||
static const char* g_terrainFollow = "mainwindow/terrainFollow";
|
||||
|
||||
class CEditorOpenViewCommand
|
||||
: public _i_reference_target_t
|
||||
{
|
||||
@@ -308,10 +300,8 @@ namespace
|
||||
|
||||
class SnapToWidget
|
||||
: public QWidget
|
||||
, public CGridSettingsDialog::NotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
|
||||
typedef AZStd::function<void(double)> SetValueCallback;
|
||||
typedef AZStd::function<double()> GetValueCallback;
|
||||
|
||||
@@ -335,12 +325,13 @@ public:
|
||||
m_spinBox->setEnabled(defaultAction->isChecked());
|
||||
m_spinBox->setMinimum(1e-2f);
|
||||
|
||||
OnGridValuesUpdated();
|
||||
{
|
||||
QSignalBlocker signalBlocker(m_spinBox);
|
||||
m_spinBox->setValue(m_getValueCallback());
|
||||
}
|
||||
|
||||
QObject::connect(m_spinBox, QOverload<double>::of(&AzQtComponents::DoubleSpinBox::valueChanged), this, &SnapToWidget::OnValueChanged);
|
||||
QObject::connect(defaultAction, &QAction::changed, this, &SnapToWidget::OnActionChanged);
|
||||
|
||||
CGridSettingsDialog::NotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void SetIcon(QIcon icon)
|
||||
@@ -348,14 +339,6 @@ public:
|
||||
m_toolButton->setIcon(icon);
|
||||
}
|
||||
|
||||
void OnGridValuesUpdated() override
|
||||
{
|
||||
// Blocking signals to not trigger the valueChanged callback when we set the value on the spin box.
|
||||
QSignalBlocker signalBlocker(m_spinBox);
|
||||
double value = m_getValueCallback();
|
||||
m_spinBox->setValue(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void OnValueChanged(double value)
|
||||
@@ -543,7 +526,6 @@ void MainWindow::Initialize()
|
||||
RegisterStdViewClasses();
|
||||
InitCentralWidget();
|
||||
|
||||
LoadConfig();
|
||||
InitActions();
|
||||
|
||||
// load toolbars ("shelves") and macros
|
||||
@@ -673,31 +655,8 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::LoadConfig()
|
||||
{
|
||||
CGrid* grid = gSettings.pGrid;
|
||||
Q_ASSERT(grid);
|
||||
bool terrainValue;
|
||||
|
||||
ReadConfigValue(g_snapAngleEnabled, grid->bAngleSnapEnabled);
|
||||
ReadConfigValue(g_snapAngle, grid->angleSnap);
|
||||
ReadConfigValue(g_snapToGridEnabled, grid->bEnabled);
|
||||
ReadConfigValue(g_snapToGridSize, grid->size);
|
||||
ReadConfigValue(g_terrainFollow, terrainValue);
|
||||
GetIEditor()->SetTerrainAxisIgnoreObjects(terrainValue);
|
||||
}
|
||||
|
||||
void MainWindow::SaveConfig()
|
||||
{
|
||||
CGrid* grid = gSettings.pGrid;
|
||||
Q_ASSERT(grid);
|
||||
|
||||
m_settings.setValue(g_snapAngleEnabled, grid->bAngleSnapEnabled);
|
||||
m_settings.setValue(g_snapAngle, grid->angleSnap);
|
||||
m_settings.setValue(g_snapToGridEnabled, grid->bEnabled);
|
||||
m_settings.setValue(g_snapToGridSize, grid->size);
|
||||
m_settings.setValue(g_terrainFollow, GetIEditor()->IsTerrainAxisIgnoreObjects());
|
||||
|
||||
m_settings.setValue("mainWindowState", saveState());
|
||||
QtViewPaneManager::instance()->SaveLayout();
|
||||
if (m_pLayoutWnd)
|
||||
@@ -941,7 +900,6 @@ void MainWindow::InitActions()
|
||||
.SetStatusTip(tr("Render in Wireframe Mode."))
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateWireframe);
|
||||
|
||||
am->AddAction(ID_VIEW_GRIDSETTINGS, tr("Grid Settings..."));
|
||||
am->AddAction(ID_SWITCHCAMERA_DEFAULTCAMERA, tr("Default Camera")).SetCheckable(true)
|
||||
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSwitchToDefaultCamera);
|
||||
am->AddAction(ID_SWITCHCAMERA_SEQUENCECAMERA, tr("Sequence Camera")).SetCheckable(true)
|
||||
@@ -1479,15 +1437,6 @@ MainStatusBar* MainWindow::StatusBar() const
|
||||
return static_cast<MainStatusBar*>(statusBar());
|
||||
}
|
||||
|
||||
void MainWindow::OnUpdateSnapToGrid(QAction* action)
|
||||
{
|
||||
Q_ASSERT(action->isCheckable());
|
||||
bool bEnabled = gSettings.pGrid->IsEnabled();
|
||||
action->setChecked(bEnabled);
|
||||
|
||||
action->setText(QObject::tr("Snap To Grid"));
|
||||
}
|
||||
|
||||
KeyboardCustomizationSettings* MainWindow::GetShortcutManager() const
|
||||
{
|
||||
return m_keyboardCustomization;
|
||||
|
||||
@@ -191,9 +191,7 @@ private:
|
||||
void InitToolActionHandlers();
|
||||
void InitToolBars();
|
||||
void InitStatusBar();
|
||||
void OnUpdateSnapToGrid(QAction* action);
|
||||
void OnViewPaneCreated(const QtViewPane* pane);
|
||||
void LoadConfig();
|
||||
|
||||
template <class TValue>
|
||||
void ReadConfigValue(const QString& key, TValue& value)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
@@ -64,17 +65,20 @@ namespace SandboxEditor
|
||||
}
|
||||
}
|
||||
|
||||
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller)
|
||||
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(
|
||||
const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller)
|
||||
: MultiViewportControllerInstanceInterface<ModernViewportCameraController>(viewportId, controller)
|
||||
{
|
||||
controller->SetupCameras(m_cameraSystem.m_cameras);
|
||||
|
||||
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
|
||||
{
|
||||
auto handleCameraChange = [this](const AZ::Matrix4x4& matrix) {
|
||||
UpdateCameraFromTransform(
|
||||
m_targetCamera,
|
||||
AZ::Transform::CreateFromMatrix3x3AndTranslation(AZ::Matrix3x3::CreateFromMatrix4x4(matrix), matrix.GetTranslation()));
|
||||
auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&) {
|
||||
if (!m_updatingTransform)
|
||||
{
|
||||
UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform());
|
||||
m_camera = m_targetCamera;
|
||||
}
|
||||
};
|
||||
|
||||
m_cameraViewMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange);
|
||||
@@ -124,6 +128,8 @@ namespace SandboxEditor
|
||||
{
|
||||
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
|
||||
{
|
||||
m_updatingTransform = true;
|
||||
|
||||
if (m_cameraMode == CameraMode::Control)
|
||||
{
|
||||
m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count());
|
||||
@@ -155,6 +161,8 @@ namespace SandboxEditor
|
||||
|
||||
viewportContext->SetCameraTransform(current);
|
||||
}
|
||||
|
||||
m_updatingTransform = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,14 +20,13 @@
|
||||
namespace SandboxEditor
|
||||
{
|
||||
class ModernViewportCameraControllerInstance;
|
||||
class ModernViewportCameraController
|
||||
: public AzFramework::MultiViewportController<ModernViewportCameraControllerInstance>
|
||||
class ModernViewportCameraController : public AzFramework::MultiViewportController<ModernViewportCameraControllerInstance>
|
||||
{
|
||||
public:
|
||||
using CameraListBuilder = AZStd::function<void(AzFramework::Cameras&)>;
|
||||
|
||||
//! Sets the camera list builder callback used to populate new ModernViewportCameraControllerInstances
|
||||
void SetCameraListBuilderCallback(const CameraListBuilder& builder);
|
||||
|
||||
//! Sets up a camera list based on this controller's CameraListBuilderCallback
|
||||
void SetupCameras(AzFramework::Cameras& cameras);
|
||||
|
||||
@@ -35,9 +34,9 @@ namespace SandboxEditor
|
||||
CameraListBuilder m_cameraListBuilder;
|
||||
};
|
||||
|
||||
class ModernViewportCameraControllerInstance final
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModernViewportCameraController>
|
||||
, private AzFramework::ViewportDebugDisplayEventBus::Handler
|
||||
class ModernViewportCameraControllerInstance final
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModernViewportCameraController>,
|
||||
private AzFramework::ViewportDebugDisplayEventBus::Handler
|
||||
{
|
||||
public:
|
||||
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModernViewportCameraController* controller);
|
||||
@@ -65,6 +64,7 @@ namespace SandboxEditor
|
||||
AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity();
|
||||
float m_animationT = 0.0f;
|
||||
CameraMode m_cameraMode = CameraMode::Control;
|
||||
bool m_updatingTransform = false;
|
||||
|
||||
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// Editor
|
||||
#include "Viewport.h"
|
||||
#include "GizmoManager.h"
|
||||
#include "Grid.h"
|
||||
#include "ViewManager.h"
|
||||
#include "Settings.h"
|
||||
#include "RenderHelpers/AxisHelper.h"
|
||||
@@ -244,7 +243,8 @@ Matrix34 CAxisGizmo::GetTransformation(RefCoordSys coordSys, IDisplayViewport* v
|
||||
break;
|
||||
case COORDS_USERDEFINED:
|
||||
{
|
||||
Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix();
|
||||
Matrix34 userTM;
|
||||
userTM.SetIdentity();
|
||||
userTM.SetTranslation(m_object->GetWorldTM().GetTranslation());
|
||||
return userTM;
|
||||
}
|
||||
|
||||
@@ -1268,12 +1268,6 @@ int CBaseObject::MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint&
|
||||
if (event == eMouseWheel)
|
||||
{
|
||||
double angle = 1;
|
||||
|
||||
if (view->GetViewManager()->GetGrid()->IsAngleSnapEnabled())
|
||||
{
|
||||
angle = view->GetViewManager()->GetGrid()->GetAngleSnap();
|
||||
}
|
||||
|
||||
Quat rot = GetRotation();
|
||||
rot.SetRotationXYZ(Ang3(0, 0, rot.GetRotZ() + DEG2RAD(flags > 0 ? angle * (-1) : angle)));
|
||||
SetRotation(rot);
|
||||
|
||||
@@ -342,7 +342,8 @@ void CSelectionGroup::Rotate(const Matrix34& rotateTM, int referenceCoordSys)
|
||||
|
||||
if (referenceCoordSys == COORDS_USERDEFINED)
|
||||
{
|
||||
Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix();
|
||||
Matrix34 userTM;
|
||||
userTM.SetIdentity();
|
||||
Matrix34 invUserTM = userTM.GetInvertedFast();
|
||||
|
||||
ToOrigin = invUserTM * ToOrigin;
|
||||
|
||||
@@ -1985,28 +1985,27 @@ AzFramework::CameraState CRenderViewport::GetCameraState()
|
||||
|
||||
bool CRenderViewport::GridSnappingEnabled()
|
||||
{
|
||||
return GetViewManager()->GetGrid()->IsEnabled();
|
||||
return false;
|
||||
}
|
||||
|
||||
float CRenderViewport::GridSize()
|
||||
{
|
||||
const CGrid* grid = GetViewManager()->GetGrid();
|
||||
return grid->scale * grid->size;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool CRenderViewport::ShowGrid()
|
||||
{
|
||||
return gSettings.viewports.bShowGridGuide;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CRenderViewport::AngleSnappingEnabled()
|
||||
{
|
||||
return GetViewManager()->GetGrid()->IsAngleSnapEnabled();
|
||||
return false;
|
||||
}
|
||||
|
||||
float CRenderViewport::AngleStep()
|
||||
{
|
||||
return GetViewManager()->GetGrid()->GetAngleSnap();
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
AZ::Vector3 CRenderViewport::PickTerrain(const AzFramework::ScreenPoint& point)
|
||||
@@ -3882,94 +3881,13 @@ void CRenderViewport::ActivateWindowAndSetFocus()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRenderViewport::RenderConstructionPlane()
|
||||
{
|
||||
DisplayContext& dc = m_displayContext;
|
||||
|
||||
int prevState = dc.GetState();
|
||||
dc.DepthWriteOff();
|
||||
// Draw Construction plane.
|
||||
|
||||
CGrid* pGrid = GetViewManager()->GetGrid();
|
||||
|
||||
RefCoordSys coordSys = COORDS_WORLD;
|
||||
|
||||
Vec3 p = m_constructionMatrix[coordSys].GetTranslation();
|
||||
Vec3 n = m_constructionPlane.n;
|
||||
|
||||
Vec3 u = Vec3(1, 0, 0);
|
||||
Vec3 v = Vec3(0, 1, 0);
|
||||
|
||||
|
||||
if (gSettings.snap.bGridUserDefined)
|
||||
{
|
||||
Ang3 angles = Ang3(pGrid->rotationAngles.x * gf_PI / 180.0, pGrid->rotationAngles.y * gf_PI / 180.0, pGrid->rotationAngles.z * gf_PI / 180.0);
|
||||
Matrix34 tm = Matrix33::CreateRotationXYZ(angles);
|
||||
|
||||
u = tm * u;
|
||||
v = tm * v;
|
||||
}
|
||||
|
||||
float step = pGrid->scale * pGrid->size;
|
||||
float size = gSettings.snap.constructPlaneSize;
|
||||
|
||||
dc.SetColor(0, 0, 1, 0.1f);
|
||||
|
||||
float s = size;
|
||||
|
||||
dc.DrawQuad(p - u * s - v * s, p + u * s - v * s, p + u * s + v * s, p - u * s + v * s);
|
||||
|
||||
int nSteps = int(size / step);
|
||||
int i;
|
||||
// Draw X lines.
|
||||
dc.SetColor(1, 0, 0.2f, 0.3f);
|
||||
|
||||
for (i = -nSteps; i <= nSteps; i++)
|
||||
{
|
||||
dc.DrawLine(p - u * size + v * (step * i), p + u * size + v * (step * i));
|
||||
}
|
||||
// Draw Y lines.
|
||||
dc.SetColor(0.2f, 1.0f, 0, 0.3f);
|
||||
for (i = -nSteps; i <= nSteps; i++)
|
||||
{
|
||||
dc.DrawLine(p - v * size + u * (step * i), p + v * size + u * (step * i));
|
||||
}
|
||||
|
||||
// Draw origin lines.
|
||||
|
||||
dc.SetLineWidth(2);
|
||||
|
||||
//X
|
||||
dc.SetColor(1, 0, 0);
|
||||
dc.DrawLine(p - u * s, p + u * s);
|
||||
|
||||
//Y
|
||||
dc.SetColor(0, 1, 0);
|
||||
dc.DrawLine(p - v * s, p + v * s);
|
||||
|
||||
//Z
|
||||
dc.SetColor(0, 0, 1);
|
||||
dc.DrawLine(p - n * s, p + n * s);
|
||||
|
||||
dc.SetLineWidth(0);
|
||||
|
||||
dc.SetState(prevState);
|
||||
// noop
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRenderViewport::RenderSnappingGrid()
|
||||
{
|
||||
// First, Check whether we should draw the grid or not.
|
||||
CGrid* pGrid = GetViewManager()->GetGrid();
|
||||
if (pGrid->IsEnabled() == false && pGrid->IsAngleSnapEnabled() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayContext& dc = m_displayContext;
|
||||
|
||||
int prevState = dc.GetState();
|
||||
dc.DepthWriteOff();
|
||||
|
||||
dc.SetState(prevState);
|
||||
// noop
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
#define ID_EDIT_HIDE 32898
|
||||
#define ID_EDIT_UNHIDEALL 32899
|
||||
#define ID_RELOAD_TERRAIN 32902
|
||||
#define ID_VIEW_GRIDSETTINGS 32904
|
||||
#define ID_VIEW_CONFIGURELAYOUT 32906
|
||||
#define ID_TOOLS_LOGMEMORYUSAGE 32908
|
||||
#define ID_TERRAIN_EXPORTBLOCK 32909
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/ToolBar.h>
|
||||
|
||||
class CGrid;
|
||||
|
||||
struct SGizmoSettings
|
||||
{
|
||||
float axisGizmoSize;
|
||||
@@ -393,9 +391,6 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
//! Keeps the editor active even if no focus is set
|
||||
int keepEditorActive;
|
||||
|
||||
//! Pointer to currently used grid.
|
||||
CGrid* pGrid;
|
||||
|
||||
SGizmoSettings gizmo;
|
||||
|
||||
// Settings of the snapping.
|
||||
|
||||
@@ -49,8 +49,6 @@ bool CViewManager::IsMultiViewportEnabled()
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CViewManager::CViewManager()
|
||||
{
|
||||
gSettings.pGrid = &m_grid;
|
||||
|
||||
m_zoomFactor = 1;
|
||||
|
||||
m_origin2D(0, 0, 0);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cry_Geo.h"
|
||||
#include "Grid.h"
|
||||
#include "Viewport.h"
|
||||
#include "Include/IViewPane.h"
|
||||
#include "QtViewPaneManager.h"
|
||||
@@ -67,10 +66,6 @@ public:
|
||||
void SetUpdateRegion(const AABB& updateRegion) { m_updateRegion = updateRegion; };
|
||||
const AABB& GetUpdateRegion() { return m_updateRegion; };
|
||||
|
||||
/** Retrieve Grid used for viewes.
|
||||
*/
|
||||
CGrid* GetGrid() { return &m_grid; };
|
||||
|
||||
/** Get 2D viewports origin.
|
||||
*/
|
||||
Vec3 GetOrigin2D() const { return m_origin2D; }
|
||||
@@ -137,7 +132,6 @@ private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AABB m_updateRegion;
|
||||
|
||||
CGrid m_grid;
|
||||
//! Origin of 2d viewports.
|
||||
Vec3 m_origin2D;
|
||||
//! Zoom of 2d viewports.
|
||||
|
||||
@@ -1182,12 +1182,12 @@ float QtViewport::GetZoomFactor() const
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 QtViewport::SnapToGrid(const Vec3& vec)
|
||||
{
|
||||
return m_viewManager->GetGrid()->Snap(vec, m_fGridZoom);
|
||||
return vec;
|
||||
}
|
||||
|
||||
float QtViewport::GetGridStep() const
|
||||
{
|
||||
return m_viewManager->GetGrid()->scale * m_viewManager->GetGrid()->size;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -437,9 +437,6 @@ set(FILES
|
||||
GotoPositionDlg.cpp
|
||||
GotoPositionDlg.h
|
||||
GotoPositionDlg.ui
|
||||
GridSettingsDialog.cpp
|
||||
GridSettingsDialog.h
|
||||
GridSettingsDialog.ui
|
||||
InfoBar.cpp
|
||||
InfoBar.qrc
|
||||
InfoBar.h
|
||||
@@ -835,8 +832,6 @@ set(FILES
|
||||
WelcomeScreen/WelcomeScreenDialog.qrc
|
||||
2DViewport.cpp
|
||||
2DViewport.h
|
||||
Grid.cpp
|
||||
Grid.h
|
||||
LayoutWnd.cpp
|
||||
LayoutWnd.h
|
||||
EditorViewportWidget.cpp
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <LinkWidget.h>
|
||||
#include <QDesktopServices>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
LinkLabel::LinkLabel(const QString& text, const QUrl& url, QWidget* parent)
|
||||
: QLabel(text, parent)
|
||||
, m_url(url)
|
||||
{
|
||||
SetDefaultStyle();
|
||||
}
|
||||
|
||||
void LinkLabel::mousePressEvent([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
QDesktopServices::openUrl(m_url);
|
||||
}
|
||||
|
||||
void LinkLabel::enterEvent([[maybe_unused]] QEvent* event)
|
||||
{
|
||||
setStyleSheet("font-size: 9pt; color: #94D2FF; text-decoration: underline;");
|
||||
}
|
||||
|
||||
void LinkLabel::leaveEvent([[maybe_unused]] QEvent* event)
|
||||
{
|
||||
SetDefaultStyle();
|
||||
}
|
||||
|
||||
void LinkLabel::SetUrl(const QUrl& url)
|
||||
{
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
void LinkLabel::SetDefaultStyle()
|
||||
{
|
||||
setStyleSheet("font-size: 9pt; color: #94D2FF;");
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
+18
-20
@@ -12,33 +12,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzQtComponents/Components/StyledDialog.h>
|
||||
#include <QLabel>
|
||||
#include <QUrl>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ImagePopup;
|
||||
}
|
||||
QT_FORWARD_DECLARE_CLASS(QEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QMouseEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QWidget)
|
||||
|
||||
namespace ImageProcessingEditor
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ImagePopup
|
||||
: public QDialog
|
||||
class LinkLabel
|
||||
: public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ImagePopup, AZ::SystemAllocator, 0);
|
||||
explicit ImagePopup(QImage previewImage, QWidget* parent = nullptr);
|
||||
~ImagePopup();
|
||||
LinkLabel(const QString& text, const QUrl& url = {}, QWidget* parent = nullptr);
|
||||
|
||||
void SetUrl(const QUrl& url);
|
||||
private:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void enterEvent(QEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
void SetDefaultStyle();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ImagePopup> m_ui;
|
||||
QImage m_previewImage;
|
||||
|
||||
QUrl m_url;
|
||||
};
|
||||
} //namespace ImageProcessingEditor
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TagWidget.h>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
TagWidget::TagWidget(const QString& text, QWidget* parent)
|
||||
: QLabel(text, parent)
|
||||
{
|
||||
setFixedHeight(35);
|
||||
setMargin(5);
|
||||
setStyleSheet("font-size: 12pt; background-color: #333333; border-radius: 4px;");
|
||||
}
|
||||
|
||||
TagContainerWidget::TagContainerWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_layout = new QVBoxLayout();
|
||||
m_layout->setAlignment(Qt::AlignTop);
|
||||
m_layout->setMargin(0);
|
||||
setLayout(m_layout);
|
||||
}
|
||||
|
||||
void TagContainerWidget::Update(const QStringList& tags)
|
||||
{
|
||||
QWidget* parentWidget = qobject_cast<QWidget*>(parent());
|
||||
int width = 250;
|
||||
if (parentWidget)
|
||||
{
|
||||
width = parentWidget->width();
|
||||
}
|
||||
|
||||
if (m_widget)
|
||||
{
|
||||
// Hide the old widget and request deletion.
|
||||
m_widget->hide();
|
||||
m_widget->deleteLater();
|
||||
}
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
m_widget = new QWidget(this);
|
||||
m_widget->setLayout(vLayout);
|
||||
m_layout->addWidget(m_widget);
|
||||
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
vLayout->setMargin(0);
|
||||
|
||||
QHBoxLayout* hLayout = nullptr;
|
||||
int usedSpaceInRow = 0;
|
||||
const int numTags = tags.count();
|
||||
|
||||
for (int i = 0; i < numTags; ++i)
|
||||
{
|
||||
// Create the new tag widget.
|
||||
TagWidget* tagWidget = new TagWidget(tags[i]);
|
||||
const int tagWidgetWidth = tagWidget->minimumSizeHint().width();
|
||||
|
||||
// Calculate the width we're currently using in the current row. Does the new tag still fit in the current row?
|
||||
const bool isRowFull = width - usedSpaceInRow - tagWidgetWidth < 0;
|
||||
if (isRowFull || i == 0)
|
||||
{
|
||||
// Add a spacer widget after the last tag widget in a row to push the tag widgets to the left.
|
||||
if (i > 0)
|
||||
{
|
||||
QWidget* spacerWidget = new QWidget();
|
||||
spacerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
|
||||
hLayout->addWidget(spacerWidget);
|
||||
}
|
||||
|
||||
// Add a new row for the current tag widget.
|
||||
hLayout = new QHBoxLayout();
|
||||
hLayout->setAlignment(Qt::AlignLeft);
|
||||
hLayout->setMargin(0);
|
||||
vLayout->addLayout(hLayout);
|
||||
|
||||
// Reset the used space in the row.
|
||||
usedSpaceInRow = 0;
|
||||
}
|
||||
|
||||
// Calculate the width of the tag widgets including the spacing between them of the current row.
|
||||
usedSpaceInRow += tagWidgetWidth + hLayout->spacing();
|
||||
|
||||
// Add the tag widget to the current row.
|
||||
hLayout->addWidget(tagWidget);
|
||||
}
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QLabel>
|
||||
#include <QStringList>
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
// Single tag
|
||||
class TagWidget
|
||||
: public QLabel
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit TagWidget(const QString& text, QWidget* parent = nullptr);
|
||||
~TagWidget() = default;
|
||||
};
|
||||
|
||||
// Widget containing multiple tags, automatically wrapping based on the size
|
||||
class TagContainerWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit TagContainerWidget(QWidget* parent = nullptr);
|
||||
~TagContainerWidget() = default;
|
||||
|
||||
void Update(const QStringList& tags);
|
||||
|
||||
private:
|
||||
QVBoxLayout* m_layout = nullptr;
|
||||
QWidget* m_widget = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -34,6 +34,10 @@ set(FILES
|
||||
Source/EngineSettings.h
|
||||
Source/EngineSettings.cpp
|
||||
Source/EngineSettings.ui
|
||||
Source/LinkWidget.h
|
||||
Source/LinkWidget.cpp
|
||||
Source/TagWidget.h
|
||||
Source/TagWidget.cpp
|
||||
Source/GemCatalog/GemCatalog.h
|
||||
Source/GemCatalog/GemCatalog.cpp
|
||||
Source/GemCatalog/GemInfo.h
|
||||
|
||||
@@ -95,32 +95,32 @@ namespace UnitTest
|
||||
class ImageProcessingTest
|
||||
: public ::testing::Test
|
||||
, public AllocatorsBase
|
||||
, public ComponentApplicationBus::Handler
|
||||
, public AZ::ComponentApplicationBus::Handler
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ComponentApplicationMessages.
|
||||
ComponentApplication* GetApplication() override { return nullptr; }
|
||||
void RegisterComponentDescriptor(const ComponentDescriptor*) override { }
|
||||
void UnregisterComponentDescriptor(const ComponentDescriptor*) override { }
|
||||
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { }
|
||||
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { }
|
||||
void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { }
|
||||
void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { }
|
||||
void SignalEntityActivated(Entity*) override { }
|
||||
void SignalEntityDeactivated(Entity*) override { }
|
||||
bool AddEntity(Entity*) override { return false; }
|
||||
bool RemoveEntity(Entity*) override { return false; }
|
||||
bool DeleteEntity(const EntityId&) override { return false; }
|
||||
Entity* FindEntity(const EntityId&) override { return nullptr; }
|
||||
SerializeContext* GetSerializeContext() override { return m_context.get(); }
|
||||
BehaviorContext* GetBehaviorContext() override { return nullptr; }
|
||||
AZ::ComponentApplication* GetApplication() override { return nullptr; }
|
||||
void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
|
||||
void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
|
||||
void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
|
||||
void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
|
||||
void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
|
||||
void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
|
||||
void SignalEntityActivated(AZ::Entity*) override { }
|
||||
void SignalEntityDeactivated(AZ::Entity*) override { }
|
||||
bool AddEntity(AZ::Entity*) override { return false; }
|
||||
bool RemoveEntity(AZ::Entity*) override { return false; }
|
||||
bool DeleteEntity(const AZ::EntityId&) override { return false; }
|
||||
Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
|
||||
AZ::SerializeContext* GetSerializeContext() override { return m_context.get(); }
|
||||
AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
|
||||
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return m_jsonRegistrationContext.get(); }
|
||||
const char* GetAppRoot() const override { return nullptr; }
|
||||
const char* GetEngineRoot() const override { return nullptr; }
|
||||
const char* GetExecutableFolder() const override { return nullptr; }
|
||||
Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
|
||||
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
|
||||
AZ::Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
|
||||
void EnumerateEntities(const AZ::ComponentApplicationRequests::EntityCallback& /*callback*/) override {}
|
||||
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
@@ -166,6 +167,18 @@ namespace AZ
|
||||
|
||||
RPI::RPISystemInterface::Get()->InitializeSystemAssets();
|
||||
|
||||
if (!RPI::RPISystemInterface::Get()->IsInitialized())
|
||||
{
|
||||
AZ::OSString msgBoxMessage;
|
||||
msgBoxMessage.append("RPI System could not initialize correctly. Check log for detail.");
|
||||
|
||||
AZ::NativeUI::NativeUIRequestBus::Broadcast(
|
||||
&AZ::NativeUI::NativeUIRequestBus::Events::DisplayOkDialog, "O3DE Fatal Error", msgBoxMessage.c_str(), false);
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// In the case of the game we want to call create and register the scene as a soon as we can
|
||||
// because a level could be loaded in autoexec.cfg and that will assert if there is no scene registered
|
||||
// to get the feature processors for the components. So we can't wait until the tick (whereas the Editor wants to wait)
|
||||
|
||||
@@ -37,8 +37,6 @@ float3 TextureBlend_Overlay(float3 target, float3 blend)
|
||||
//! @return the resulting blended color
|
||||
float3 ApplyTextureBlend(float3 color, float3 blendColor, float factor, TextureBlendMode blendMode)
|
||||
{
|
||||
// More info to help understand some of these blend modes: https://wiki.agscollab.com/pages/viewpage.action?pageId=15764930
|
||||
|
||||
if(blendMode == TextureBlendMode::Multiply)
|
||||
{
|
||||
return factor * color * blendColor;
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class LightCullingTileIterator
|
||||
|
||||
float viewz = abs(svPosition.w);
|
||||
|
||||
// https://jira.agscollab.com/browse/ATOM-4198
|
||||
// ATOM-4198
|
||||
// Replace GetDimensions() with a cbuffer uint read. Reading it from a cbuffer should be faster
|
||||
uint tileWidth, tileHeight;
|
||||
tileLightDataTex.GetDimensions(tileWidth, tileHeight);
|
||||
|
||||
+72
-2
@@ -13,6 +13,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Features/PBR/Lights/LightTypesCommon.azsli>
|
||||
#include <Atom/Features/Shadow/ProjectedShadow.azsli>
|
||||
|
||||
// The order should match m_pointShadowTransforms in PointLightFeatureProcessor.h/.cpp
|
||||
static const float3 PointLightShadowCubemapDirections[6] = {float3(-1,0,0), float3(1,0,0), float3(0,-1,0), float3(0,1,0), float3(0,0,-1), float3(0,0,1)};
|
||||
|
||||
int GetPointLightShadowCubemapFace(const float3 targetPos, const float3 lightPos)
|
||||
{
|
||||
const float3 toPoint = targetPos - lightPos;
|
||||
const float maxElement = max(abs(toPoint.z), max(abs(toPoint.x), abs(toPoint.y)));
|
||||
if (toPoint.x == -maxElement)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (toPoint.x == maxElement)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (toPoint.y == -maxElement)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (toPoint.y == maxElement)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (toPoint.z == -maxElement)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
// PointLight::m_shadowIndices actually consists of uint16_t x 6 on the CPU, but visible as a uint32_t x 3 on the GPU.
|
||||
// This function returns the proper uint16_t value given an input face in the range 0-5
|
||||
int UnpackPointLightShadowIndex(const ViewSrg::PointLight light, const int face)
|
||||
{
|
||||
const int index = face >> 1;
|
||||
const int shiftAmount = (face & 1) * 16;
|
||||
return (light.m_shadowIndices[index] >> shiftAmount) & 0xFFFF;
|
||||
}
|
||||
|
||||
void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingData lightingData)
|
||||
{
|
||||
@@ -31,11 +74,38 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
|
||||
d2 = max(0.001 * 0.001, d2); // clamp the light to at least 1mm away to avoid extreme values.
|
||||
float3 lightIntensity = (light.m_rgbIntensityCandelas / d2) * radiusAttenuation;
|
||||
|
||||
// shadow
|
||||
float litRatio = 1.0;
|
||||
|
||||
// How much is back face shadowed, it's set to the reverse of litRatio to share the same default value with thickness, which should be 0 if no shadow map available
|
||||
float backShadowRatio = 0.0;
|
||||
if (o_enableShadows)
|
||||
{
|
||||
const int shadowCubemapFace = GetPointLightShadowCubemapFace(surface.position, light.m_position);
|
||||
const int shadowIndex = UnpackPointLightShadowIndex(light, shadowCubemapFace);
|
||||
|
||||
litRatio *= ProjectedShadow::GetVisibility(
|
||||
shadowIndex,
|
||||
light.m_position,
|
||||
surface.position,
|
||||
PointLightShadowCubemapDirections[shadowCubemapFace],
|
||||
surface.normal);
|
||||
|
||||
// Use backShadowRatio to carry thickness from shadow map for thick mode
|
||||
backShadowRatio = 1.0 - litRatio;
|
||||
if (o_transmission_mode == TransmissionMode::ThickObject)
|
||||
{
|
||||
backShadowRatio = ProjectedShadow::GetThickness(
|
||||
shadowIndex,
|
||||
surface.position);
|
||||
}
|
||||
}
|
||||
|
||||
// Diffuse contribution
|
||||
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight));
|
||||
lightingData.diffuseLighting += GetDiffuseLighting(surface, lightingData, lightIntensity, normalize(posToLight)) * litRatio;
|
||||
|
||||
// Tranmission contribution
|
||||
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), 0.0);
|
||||
lightingData.translucentBackLighting += GetBackLighting(surface, lightingData, lightIntensity, normalize(posToLight), backShadowRatio);
|
||||
|
||||
// Adjust the light direcion for specular based on bulb size
|
||||
|
||||
|
||||
+2
@@ -61,6 +61,8 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
|
||||
float m_invAttenuationRadiusSquared;
|
||||
float3 m_rgbIntensity;
|
||||
float m_bulbRadius;
|
||||
uint3 m_shadowIndices;
|
||||
uint m_padding;
|
||||
};
|
||||
|
||||
StructuredBuffer<PointLight> m_pointLights;
|
||||
|
||||
@@ -73,6 +73,8 @@ partial ShaderResourceGroup ViewSrg
|
||||
float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2.
|
||||
float3 m_rgbIntensityCandelas;
|
||||
float m_bulbRadius;
|
||||
uint3 m_shadowIndices;
|
||||
uint m_padding;
|
||||
};
|
||||
|
||||
StructuredBuffer<PointLight> m_pointLights;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <Atom/RPI/Math.azsli>
|
||||
#include <Atom/Features/LightCulling/LightCullingShared.azsli>
|
||||
|
||||
enum QuadLightFlag // Copied from QuadLight.azsli. See https://jira.agscollab.com/browse/ATOM-3731
|
||||
enum QuadLightFlag // Copied from QuadLight.azsli. See ATOM-3731
|
||||
{
|
||||
None = 0x00,
|
||||
EmitsBothDirections = 0x01, // 1 << 0, // Quad should emit light from both sides
|
||||
@@ -33,7 +33,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
{
|
||||
// Figure out how to remove duplicate struct definitions.
|
||||
// These are also defined in View.srg
|
||||
// https://jira.agscollab.com/browse/ATOM-3731
|
||||
// ATOM-3731
|
||||
|
||||
struct SimplePointLight
|
||||
{
|
||||
@@ -59,6 +59,8 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
float m_invAttenuationRadiusSquared; // For a radius at which this light no longer has an effect, 1 / radius^2.
|
||||
float3 m_rgbIntensityCandelas;
|
||||
float m_bulbRadius;
|
||||
uint3 m_shadowIndices;
|
||||
uint m_padding;
|
||||
};
|
||||
|
||||
struct DiskLight
|
||||
@@ -370,7 +372,7 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center
|
||||
float3 decalPosition = WorldToView_Point(decal.m_position);
|
||||
|
||||
// just wrapping a bounding sphere around a cube for now to get a minor perf boost. i.e. the sphere radius is sqrt(x*x + y*y + z*z)
|
||||
// https://jira.agscollab.com/browse/ATOM-4224 - try AABB-AABB and implement depth binning for the decals
|
||||
// ATOM-4224 - try AABB-AABB and implement depth binning for the decals
|
||||
float maxHalfSize = max(max(decal.m_halfSize.x, decal.m_halfSize.y), decal.m_halfSize.z);
|
||||
float boundingSphereRadiusSqr = maxHalfSize * maxHalfSize * 3;
|
||||
|
||||
@@ -378,7 +380,7 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center
|
||||
if (potentiallyIntersects)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
MarkLightAsVisibleInSharedMemory(decalIndex, 0xFFFF);
|
||||
}
|
||||
}
|
||||
@@ -391,7 +393,7 @@ void CullPointLight(uint lightIndex, float3 lightPosition, float invLightRadius,
|
||||
if (potentiallyIntersects)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
|
||||
uint inside = 0;
|
||||
float2 minmax = ComputePointLightMinMaxZ(rsqrt(invLightRadius), lightPosition);
|
||||
@@ -432,7 +434,7 @@ void CullSimpleSpotLights(uint groupIndex, TileLightData tileLightData, float3 a
|
||||
if (potentiallyIntersects)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
|
||||
uint inside = 0;
|
||||
float2 minmax = ComputeSimpleSpotLightMinMax(light, lightPosition);
|
||||
@@ -477,7 +479,7 @@ void CullDiskLights(uint groupIndex, TileLightData tileLightData, float3 aabb_ce
|
||||
if (potentiallyIntersects)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
|
||||
uint inside = 0;
|
||||
float2 minmax = ComputeDiskLightMinMax(light, lightPosition);
|
||||
@@ -505,7 +507,7 @@ void CullCapsuleLights(uint groupIndex, TileLightData tileLightData, float3 aabb
|
||||
if (potentiallyIntersects)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
|
||||
uint inside = 0;
|
||||
float2 minmax = ComputeCapsuleLightMinMax(light, lightMiddleView, lightFalloffRadius);
|
||||
@@ -520,7 +522,7 @@ void CullCapsuleLights(uint groupIndex, TileLightData tileLightData, float3 aabb
|
||||
void CullQuadLights(uint groupIndex, TileLightData tileLightData, float3 aabb_center, float3 aabb_extents)
|
||||
{
|
||||
// Implement and profile fine-grained light culling testing
|
||||
// https://jira.agscollab.com/browse/ATOM-3732
|
||||
// ATOM-3732
|
||||
|
||||
for (uint lightIndex = groupIndex ; lightIndex < PassSrg::m_quadLightCount ; lightIndex += TILE_DIM_X * TILE_DIM_Y)
|
||||
{
|
||||
|
||||
@@ -242,7 +242,7 @@ PSOutput MainPS(VSOutput IN)
|
||||
|
||||
// Set this value to > 0 to actually see this pass. It is currently always active.
|
||||
OUT.m_color.w = PassSrg::m_heatmapOpacity;
|
||||
// https://jira.agscollab.com/browse/ATOM-3682 (improve heatmap integration with the pass system)
|
||||
// ATOM-3682 (improve heatmap integration with the pass system)
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ void InitWriteIndices(uint3 groupID, uint baseBin, out uint writeIndices[NVLC_MA
|
||||
// light indices until it hits an END_OF_X marker
|
||||
|
||||
// Note that this code could probably be made faster with wave intrinsics
|
||||
// https://jira.agscollab.com/browse/ATOM-4104
|
||||
// ATOM-4104
|
||||
[numthreads(NUM_THREADS, 1, 1)]
|
||||
void MainCS(
|
||||
uint3 dispatchThreadID : SV_DispatchThreadID,
|
||||
|
||||
@@ -181,7 +181,7 @@ void WriteTileLightDataToMainMemory(uint groupIndex, uint3 groupID, float2 minma
|
||||
|
||||
// Note that Nvidia Light Culling framework has some additional code to better calculate this ratio
|
||||
// See cb_perFrame.fRangeThreshold in their framework. This code might be something we want to port over.
|
||||
// https://jira.agscollab.com/browse/ATOM-5554
|
||||
// ATOM-5554
|
||||
float ratio = tileZ / 1.0f;
|
||||
float logMaxBins = clamp(log2(ratio), 0.0, LOG_MAX_BINS);
|
||||
uint ulogMaxBins = uint(logMaxBins + 0.5);
|
||||
|
||||
@@ -41,7 +41,6 @@ ShaderResourceGroup PassSrg : SRG_PerDraw
|
||||
// The number of points to sample.
|
||||
// Sample 6 points around center pixel.
|
||||
// Similarly, sample around it as 12,18,24 points.
|
||||
// Please refer to “https://wiki.agscollab.com/display/ATOM/Pencil+Map” for details.
|
||||
option enum class SampleNumber
|
||||
{
|
||||
Sample6, // 6
|
||||
@@ -52,7 +51,6 @@ option enum class SampleNumber
|
||||
o_sampleNumber = SampleNumber::Sample6;
|
||||
|
||||
// Get CocRadius from dofFactor.
|
||||
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for CocRadius.
|
||||
inline float GetCocRadius(float dofFactor)
|
||||
{
|
||||
float cocRadius = dofFactor * ViewSrg::m_dof.m_cocToScreenRatio * 0.5f;
|
||||
@@ -61,14 +59,12 @@ inline float GetCocRadius(float dofFactor)
|
||||
}
|
||||
|
||||
// Calculate the texcoord U of the pencil map from cocRadius.
|
||||
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for the pencil map.
|
||||
inline float GetPencilMapTexcoordU(float cocRadius)
|
||||
{
|
||||
return cocRadius * ViewSrg::m_dof.m_pencilMapTexcoordToCocRadius + ViewSrg::m_dof.m_pencilMapFocusPointTexcoordU;
|
||||
}
|
||||
|
||||
// Get the color from the coordinate array.
|
||||
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for details of coordinates.
|
||||
inline float4 SampleColorAndDofFactor(float2 centerTexCoord, float cocRadius, int sampleIndex)
|
||||
{
|
||||
float2 sampleTexcoordOffset = PassSrg::m_sampleTexcoordsRadius[sampleIndex].xy * cocRadius;
|
||||
@@ -78,7 +74,6 @@ inline float4 SampleColorAndDofFactor(float2 centerTexCoord, float cocRadius, in
|
||||
}
|
||||
|
||||
// Load the pencil map. Since the colors are square rooted, they are decoded (linearized). This is for accuracy.
|
||||
// Please refer to https://wiki.agscollab.com/display/ATOM/Pencil+Map for the pencil map.
|
||||
inline float4 SamplePencilMap(float lensCoordX, float radius)
|
||||
{
|
||||
float2 bokehTexcoord = float2(lensCoordX, radius);
|
||||
|
||||
@@ -77,7 +77,6 @@ PSOutput MainPS(VSOutput IN)
|
||||
float3 colorSum = (float3)0;
|
||||
|
||||
// Combine from the back buffer to the front.
|
||||
// Please refer to https://wiki.agscollab.com/pages/viewpage.action?spaceKey=ATOM&title=Dof+factor+and+Buffer+composition for details
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Background
|
||||
|
||||
+50
-14
@@ -1,19 +1,20 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
#include <Atom/Feature/CoreLights/PhotometricValue.h>
|
||||
#include <Atom/Feature/CoreLights/ShadowConstants.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -22,9 +23,25 @@ namespace AZ
|
||||
|
||||
namespace Render
|
||||
{
|
||||
struct PointLightData
|
||||
{
|
||||
AZStd::array<float, 3> m_position = {{0.0f, 0.0f, 0.0f}};
|
||||
|
||||
// Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations.
|
||||
float m_invAttenuationRadiusSquared = 0.0f;
|
||||
|
||||
AZStd::array<float, 3> m_rgbIntensity = {{0.0f, 0.0f, 0.0f}};
|
||||
|
||||
// Radius of spherical light in meters.
|
||||
float m_bulbRadius = 0.0f;
|
||||
|
||||
static const int NumShadowFaces = 6;
|
||||
AZStd::array<uint16_t, NumShadowFaces> m_shadowIndices = {{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}};
|
||||
uint32_t m_padding;
|
||||
};
|
||||
|
||||
//! PointLightFeatureProcessorInterface provides an interface to acquire, release, and update a point light.
|
||||
class PointLightFeatureProcessorInterface
|
||||
: public RPI::FeatureProcessor
|
||||
class PointLightFeatureProcessorInterface : public RPI::FeatureProcessor
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::PointLightFeatureProcessorInterface, "{D3E0B016-F3C6-4C7A-A29E-0B3A4FA87806}", AZ::RPI::FeatureProcessor);
|
||||
@@ -33,7 +50,8 @@ namespace AZ
|
||||
using LightHandle = RHI::Handle<uint16_t, class PointLight>;
|
||||
static constexpr PhotometricUnit PhotometricUnitType = PhotometricUnit::Candela;
|
||||
|
||||
//! Creates a new point light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no longer needed.
|
||||
//! Creates a new point light which can be referenced by the returned LightHandle. Must be released via ReleaseLight() when no
|
||||
//! longer needed.
|
||||
virtual LightHandle AcquireLight() = 0;
|
||||
//! Releases a LightHandle which removes the point light.
|
||||
virtual bool ReleaseLight(LightHandle& handle) = 0;
|
||||
@@ -48,6 +66,24 @@ namespace AZ
|
||||
virtual void SetAttenuationRadius(LightHandle handle, float attenuationRadius) = 0;
|
||||
//! Sets the bulb radius for the provided LightHandle. Values greater than zero effectively make it a spherical light.
|
||||
virtual void SetBulbRadius(LightHandle handle, float bulbRadius) = 0;
|
||||
//! Sets if shadows are enabled
|
||||
virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0;
|
||||
//! Sets the shadowmap size (width and height) of the light.
|
||||
virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0;
|
||||
//! Specifies filter method of shadows.
|
||||
virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0;
|
||||
//! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on
|
||||
//! the boundary. 0 disables softening.
|
||||
virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0;
|
||||
//! Sets sample count to predict boundary of shadow (up to 16). It will be clamped to be less than or equal to the filtering
|
||||
//! sample count.
|
||||
virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets sample count for filtering of shadow boundary (up to 64)
|
||||
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets the shadowmap Pcf (percentage closer filtering) method.
|
||||
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
|
||||
//! Sets all of the the point data for the provided LightHandle.
|
||||
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -1487,7 +1487,6 @@ namespace AZ
|
||||
float depthNear,
|
||||
float depthFar) const
|
||||
{
|
||||
// For calculation, refer https://wiki.agscollab.com/display/ATOM/Cascaded+Shadowmaps
|
||||
// This calculates the center of bounding sphere for a camera view frustum.
|
||||
// By this, on the camera view (2D), the bounding sphere's center
|
||||
// shifts to the remarkable point.
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace AZ
|
||||
const float invRadiusSquared = diskLight.m_invAttenuationRadiusSquared;
|
||||
if (invRadiusSquared <= 0.f)
|
||||
{
|
||||
AZ_Assert(false, "Attenuation radius have to be set before use the light.");
|
||||
AZ_Assert(false, "Attenuation radius must be set before using the light.");
|
||||
return;
|
||||
}
|
||||
const float attenuationRadius = sqrtf(1.f / invRadiusSquared);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace AZ
|
||||
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method);
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
|
||||
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace AZ
|
||||
template <typename Functor, typename ParamType>
|
||||
void SetShadowSetting(LightHandle handle, Functor&&, ParamType&& param);
|
||||
|
||||
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor;
|
||||
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor = nullptr;
|
||||
|
||||
IndexedDataVector<DiskLightData> m_diskLightData;
|
||||
GpuBufferHandler m_lightBufferHandler;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace AZ
|
||||
const size_t NumBins = 8;
|
||||
const size_t MaxLightsPerTile = 256;
|
||||
// TODO convert this to R16_UINT. It just needs RHI support
|
||||
// https://jira.agscollab.com/browse/ATOM-3975
|
||||
// ATOM-3975
|
||||
const RHI::Format LightListRemappedFormat = RHI::Format::R32_UINT;
|
||||
|
||||
RPI::Ptr<LightCullingRemap> LightCullingRemap::Create(const RPI::PassDescriptor& descriptor)
|
||||
|
||||
@@ -44,6 +44,13 @@ namespace AZ
|
||||
PointLightFeatureProcessor::PointLightFeatureProcessor()
|
||||
: PointLightFeatureProcessorInterface()
|
||||
{
|
||||
// Note must match PointShadowDirections in PointLight.azsli
|
||||
m_pointShadowTransforms[0] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisX());
|
||||
m_pointShadowTransforms[1] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisX());
|
||||
m_pointShadowTransforms[2] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisY());
|
||||
m_pointShadowTransforms[3] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisY());
|
||||
m_pointShadowTransforms[4] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), -AZ::Vector3::CreateAxisZ());
|
||||
m_pointShadowTransforms[5] = AZ::Transform::CreateLookAt(AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisZ());
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::Activate()
|
||||
@@ -54,6 +61,7 @@ namespace AZ
|
||||
desc.m_elementCountSrgName = "m_pointLightCount";
|
||||
desc.m_elementSize = sizeof(PointLightData);
|
||||
desc.m_srgLayout = RPI::RPISystemInterface::Get()->GetViewSrgAsset()->GetLayout();
|
||||
m_shadowFeatureProcessor = GetParentScene()->GetFeatureProcessor<ProjectedShadowFeatureProcessor>();
|
||||
|
||||
m_lightBufferHandler = GpuBufferHandler(desc);
|
||||
}
|
||||
@@ -83,6 +91,15 @@ namespace AZ
|
||||
{
|
||||
if (handle.IsValid())
|
||||
{
|
||||
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
|
||||
{
|
||||
ShadowId shadowId = ShadowId(m_pointLightData.GetData(handle.GetIndex()).m_shadowIndices[i]);
|
||||
if (shadowId.IsValid())
|
||||
{
|
||||
m_shadowFeatureProcessor->ReleaseShadow(shadowId);
|
||||
}
|
||||
}
|
||||
|
||||
m_pointLightData.RemoveIndex(handle.GetIndex());
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
handle.Reset();
|
||||
@@ -148,6 +165,7 @@ namespace AZ
|
||||
lightPosition.StoreToFloat3(position.data());
|
||||
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
UpdateShadow(handle);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetAttenuationRadius(LightHandle handle, float attenuationRadius)
|
||||
@@ -177,5 +195,122 @@ namespace AZ
|
||||
return m_lightBufferHandler.GetElementCount();
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetShadowsEnabled(LightHandle handle, bool enabled)
|
||||
{
|
||||
auto& light = m_pointLightData.GetData(handle.GetIndex());
|
||||
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
|
||||
{
|
||||
ShadowId shadowId = ShadowId(light.m_shadowIndices[i]);
|
||||
if (shadowId.IsValid() && !enabled)
|
||||
{
|
||||
// Disable shadows
|
||||
m_shadowFeatureProcessor->ReleaseShadow(shadowId);
|
||||
shadowId.Reset();
|
||||
light.m_shadowIndices[i] = shadowId.GetIndex();
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
}
|
||||
else if (shadowId.IsNull() && enabled)
|
||||
{
|
||||
// Enable shadows
|
||||
light.m_shadowIndices[i] = m_shadowFeatureProcessor->AcquireShadow().GetIndex();
|
||||
|
||||
UpdateShadow(handle);
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetPointData(LightHandle handle, const PointLightData& data)
|
||||
{
|
||||
AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to PointLightFeatureProcessor::SetPointData().");
|
||||
|
||||
m_pointLightData.GetData(handle.GetIndex()) = data;
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
UpdateShadow(handle);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::UpdateShadow(LightHandle handle)
|
||||
{
|
||||
constexpr float SqrtHalf = 0.707106781187f; // sqrt(0.5);
|
||||
|
||||
const auto& pointLight = m_pointLightData.GetData(handle.GetIndex());
|
||||
for (int i = 0; i < PointLightData::NumShadowFaces; ++i)
|
||||
{
|
||||
ShadowId shadowId = ShadowId(pointLight.m_shadowIndices[i]);
|
||||
if (shadowId.IsNull())
|
||||
{
|
||||
// Early out if shadows are disabled.
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectedShadowFeatureProcessorInterface::ProjectedShadowDescriptor desc = m_shadowFeatureProcessor->GetShadowProperties(shadowId);
|
||||
// Make it slightly larger than 90 degrees to avoid artifacts on the boundary between 2 cubemap faces
|
||||
desc.m_fieldOfViewYRadians = DegToRad(91.0f);
|
||||
desc.m_transform = m_pointShadowTransforms[i];
|
||||
desc.m_transform.SetTranslation(pointLight.m_position[0], pointLight.m_position[1], pointLight.m_position[2]);
|
||||
desc.m_aspectRatio = 1.0f;
|
||||
desc.m_nearPlaneDistance = SqrtHalf * pointLight.m_bulbRadius;
|
||||
|
||||
const float invRadiusSquared = pointLight.m_invAttenuationRadiusSquared;
|
||||
if (invRadiusSquared <= 0.f)
|
||||
{
|
||||
AZ_Assert(false, "Attenuation radius must be set before using the light.");
|
||||
return;
|
||||
}
|
||||
const float attenuationRadius = sqrtf(1.f / invRadiusSquared);
|
||||
desc.m_farPlaneDistance = attenuationRadius + pointLight.m_bulbRadius;
|
||||
|
||||
m_shadowFeatureProcessor->SetShadowProperties(shadowId, desc);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Functor, typename ParamType>
|
||||
void PointLightFeatureProcessor::SetShadowSetting(LightHandle handle, Functor&& functor, ParamType&& param)
|
||||
{
|
||||
AZ_Assert(handle.IsValid(), "Invalid LightHandle passed to PointLightFeatureProcessor::SetShadowSetting().");
|
||||
|
||||
auto& light = m_pointLightData.GetData(handle.GetIndex());
|
||||
for (int lightIndex = 0; lightIndex < PointLightData::NumShadowFaces; ++lightIndex)
|
||||
{
|
||||
ShadowId shadowId = ShadowId(light.m_shadowIndices[lightIndex]);
|
||||
|
||||
AZ_Assert(shadowId.IsValid(), "Attempting to set a shadow property when shadows are not enabled.");
|
||||
if (shadowId.IsValid())
|
||||
{
|
||||
AZStd::invoke(AZStd::forward<Functor>(functor), m_shadowFeatureProcessor, shadowId, AZStd::forward<ParamType>(param));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution, shadowmapSize);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowFilterMethod, method);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPredictionSampleCount, count);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h>
|
||||
#include <Atom/Feature/Utils/GpuBufferHandler.h>
|
||||
#include <CoreLights/IndexedDataVector.h>
|
||||
#include <Shadows/ProjectedShadowFeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -24,15 +25,6 @@ namespace AZ
|
||||
|
||||
namespace Render
|
||||
{
|
||||
|
||||
struct PointLightData
|
||||
{
|
||||
AZStd::array<float, 3> m_position = { { 0.0f, 0.0f, 0.0f } };
|
||||
float m_invAttenuationRadiusSquared = 0.0f; // Inverse of the distance at which this light no longer has an effect, squared. Also used for falloff calculations.
|
||||
AZStd::array<float, 3> m_rgbIntensity = { { 0.0f, 0.0f, 0.0f } };
|
||||
float m_bulbRadius = 0.0f; // Radius of spherical light in meters.
|
||||
};
|
||||
|
||||
class PointLightFeatureProcessor final
|
||||
: public PointLightFeatureProcessorInterface
|
||||
{
|
||||
@@ -58,18 +50,34 @@ namespace AZ
|
||||
void SetPosition(LightHandle handle, const AZ::Vector3& lightPosition) override;
|
||||
void SetAttenuationRadius(LightHandle handle, float attenuationRadius) override;
|
||||
void SetBulbRadius(LightHandle handle, float bulbRadius) override;
|
||||
void SetShadowsEnabled(LightHandle handle, bool enabled) override;
|
||||
void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override;
|
||||
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
|
||||
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
void SetPointData(LightHandle handle, const PointLightData& data) override;
|
||||
|
||||
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
|
||||
uint32_t GetLightCount()const;
|
||||
|
||||
private:
|
||||
PointLightFeatureProcessor(const PointLightFeatureProcessor&) = delete;
|
||||
using ShadowId = ProjectedShadowFeatureProcessor::ShadowId;
|
||||
|
||||
static constexpr const char* FeatureProcessorName = "PointLightFeatureProcessor";
|
||||
void UpdateShadow(LightHandle handle);
|
||||
// Convenience function for forwarding requests to the ProjectedShadowFeatureProcessor
|
||||
template<typename Functor, typename ParamType>
|
||||
void SetShadowSetting(LightHandle handle, Functor&&, ParamType&& param);
|
||||
ProjectedShadowFeatureProcessor* m_shadowFeatureProcessor = nullptr;
|
||||
|
||||
IndexedDataVector<PointLightData> m_pointLightData;
|
||||
GpuBufferHandler m_lightBufferHandler;
|
||||
bool m_deviceBufferNeedsUpdate = false;
|
||||
|
||||
AZStd::array<AZ::Transform, PointLightData::NumShadowFaces> m_pointShadowTransforms;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+1
-2
@@ -50,7 +50,7 @@ namespace AZ
|
||||
|
||||
static constexpr Quality QualitySet[DepthOfField::QualityLevelMax] =
|
||||
{
|
||||
// It is the radial division count of blur kernel. See "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
|
||||
// It is the radial division count of blur kernel.
|
||||
{2, 3, 4},
|
||||
{4, 4, 4}
|
||||
};
|
||||
@@ -205,7 +205,6 @@ namespace AZ
|
||||
float scaledDiameter = ScreenApertureDiameter * 0.25f;
|
||||
|
||||
// This is the conversion factor for calculating the blend ratio from DofFactor.
|
||||
// Please refer to "https://wiki.agscollab.com/display/ATOM/Dof+factor+and+Buffer+composition" for blending of DofFactor and buffer.
|
||||
|
||||
// coc0 : Confusion circle diameter screen ratio
|
||||
// coc1 : Confusion circle diameter screen ratio of one lower blur level;
|
||||
|
||||
@@ -139,7 +139,6 @@ namespace AZ
|
||||
float m_minBokehRadiusDivision8 = 0.0f;
|
||||
|
||||
// Radial division count of bokeh blur kernel.
|
||||
// See "https://wiki.agscollab.com/display/ATOM/Pencil+Map" for details.
|
||||
uint32_t m_sampleRadialDivision2 = 0;
|
||||
uint32_t m_sampleRadialDivision4 = 0;
|
||||
uint32_t m_sampleRadialDivision8 = 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user