Merge branch 'main' into Prefab/CreatePrefab
This commit is contained in:
@@ -157,7 +157,7 @@ endif()
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::BlastTests
|
||||
TEST_SUITE sandbox
|
||||
TEST_SUITE periodic
|
||||
TEST_SERIAL TRUE
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
|
||||
TIMEOUT 3600
|
||||
|
||||
@@ -22,7 +22,7 @@ import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools.log.log_monitor
|
||||
import ly_test_tools.environment.waiter as waiter
|
||||
|
||||
@pytest.mark.SUITE_sandbox
|
||||
@pytest.mark.SUITE_periodic
|
||||
@pytest.mark.parametrize('launcher_platform', ['windows_editor'])
|
||||
@pytest.mark.parametrize('project', ['AutomatedTesting'])
|
||||
@pytest.mark.parametrize('level', ['auto_test'])
|
||||
@@ -31,14 +31,13 @@ class TestPythonAssetProcessing(object):
|
||||
unexpected_lines = []
|
||||
expected_lines = [
|
||||
'Mock asset exists',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found'
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found',
|
||||
'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found'
|
||||
]
|
||||
timeout = 180
|
||||
halt_on_unexpected = False
|
||||
|
||||
@@ -26,8 +26,9 @@ assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdB
|
||||
if (assetId.is_valid() is False):
|
||||
raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead')
|
||||
|
||||
if (assetId.to_string().endswith(':54c06b89') is False):
|
||||
raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!')
|
||||
assetIdString = assetId.to_string()
|
||||
if (assetIdString.endswith(':528cca58') is False):
|
||||
raise_and_stop(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!')
|
||||
|
||||
print ('Mock asset exists')
|
||||
|
||||
@@ -41,12 +42,12 @@ def test_azmodel_product(generatedModelAssetPath, expectedSubId):
|
||||
else:
|
||||
print(f'Expected subId for asset ({generatedModelAssetPath}) found')
|
||||
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel', '10d16e68')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel', '10a71973')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_positive.azmodel', '10130556')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_negative.azmodel', '1065724d')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_positive.azmodel', '1024be55')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_negative.azmodel', '1052c94e')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel', '10315ae0')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel', '10661093')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel', '10af8810')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel', '10f8c263')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel', '100ac47f')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel', '105d8e0c')
|
||||
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel', '1002d464')
|
||||
|
||||
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""
|
||||
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
|
||||
@@ -27,7 +26,10 @@ def get_mesh_node_names(sceneGraph):
|
||||
nodeContent = sceneGraph.get_node_content(node)
|
||||
if nodeContent is not None and nodeContent.CastWithTypeName('MeshData'):
|
||||
if sceneGraph.is_node_end_point(node) is False:
|
||||
meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node)))
|
||||
nodeName = sceneData.SceneGraphName(sceneGraph.get_node_name(node))
|
||||
nodePath = nodeName.get_path()
|
||||
if (len(nodeName.get_path())):
|
||||
meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node)))
|
||||
|
||||
# advance to next node
|
||||
if sceneGraph.has_node_sibling(node):
|
||||
@@ -54,17 +56,7 @@ def update_manifest(scene):
|
||||
meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, sourceFilenameOnly + chunkPath)) + '}'
|
||||
sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by scene manifest')
|
||||
sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup, None, None, None, 1.0)
|
||||
|
||||
# create selection node list
|
||||
pathSet = set()
|
||||
for meshIndex in range(len(meshNameList)):
|
||||
targetPath = meshNameList[meshIndex].get_path()
|
||||
if (activeMeshIndex == meshIndex):
|
||||
sceneManifest.mesh_group_select_node(meshGroup, targetPath)
|
||||
else:
|
||||
if targetPath not in pathSet:
|
||||
pathSet.update(targetPath)
|
||||
sceneManifest.mesh_group_unselect_node(meshGroup, targetPath)
|
||||
sceneManifest.mesh_group_select_node(meshGroup, chunkPath)
|
||||
|
||||
return sceneManifest.export()
|
||||
|
||||
@@ -85,4 +77,4 @@ def main():
|
||||
mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
@@ -117,7 +117,8 @@ class EditorTestHelper:
|
||||
# Set the viewport back to whatever size it was at the start and restore the pane layout
|
||||
general.set_viewport_size(int(self.viewport_size.x), int(self.viewport_size.y))
|
||||
general.set_viewport_expansion_policy("AutoExpand")
|
||||
general.set_view_pane_layout(self.viewport_layout)
|
||||
# Temporarily disabling reset of view pane layout: LYN-3120
|
||||
# general.set_view_pane_layout(self.viewport_layout)
|
||||
general.update_viewport()
|
||||
|
||||
self.log("test finished")
|
||||
|
||||
+2
@@ -53,6 +53,8 @@ class TestAltitudeFilterFilterStageToggle(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
+2
@@ -59,6 +59,8 @@ class TestAreaComponentsSliceCreationAndVisibilityToggle(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) C2627900 Verifies if a slice containing the Vegetation Layer Spawner component can be created.
|
||||
# 2.1) Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
|
||||
+2
@@ -63,6 +63,8 @@ class TestDistanceBetweenFilterComponentOverrides(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
spawner_center_point = math.Vector3(520.0, 520.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "1m_cube.dynamicslice")
|
||||
|
||||
+2
@@ -61,6 +61,8 @@ class TestDistanceBetweenFilterComponent(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components
|
||||
spawner_center_point = math.Vector3(520.0, 520.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "1m_cube.dynamicslice")
|
||||
|
||||
+1
@@ -43,6 +43,7 @@ class TestDynamicSliceInstanceSpawner(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Grab the UUID that we need for creating an Dynamic Slice Instance Spawner
|
||||
dynamic_slice_spawner_uuid = azlmbr.math.Uuid_CreateString('{BBA5CC1E-B4CA-4792-89F7-93711E98FBD1}', 0)
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ class TestDynamicSliceInstanceSpawnerEmbeddedEditor(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and Script Canvas component for launcher test
|
||||
center_point = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create a new entity with required vegetation area components and switch the Vegetation Asset List Source
|
||||
# Type to External
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
|
||||
+1
@@ -43,6 +43,7 @@ class TestEmptyInstanceSpawner(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
general.idle_wait(1.0)
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Grab the UUID that we need for creating an Empty Spawner
|
||||
empty_spawner_uuid = azlmbr.math.Uuid_CreateString('{23C40FD4-A55F-4BD3-BE5B-DC5423F217C2}', 0)
|
||||
|
||||
+2
@@ -60,6 +60,8 @@ class TestLayerSpawnerInheritBehavior(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create Emitter entity and add the required components
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
emitter_entity = dynveg.create_surface_entity("emitter_entity", position, 16.0, 16.0, 1.0)
|
||||
|
||||
+3
@@ -61,6 +61,9 @@ class test_MeshBlocker_InstancesBlockedByMesh(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(500.49, 498.69, 46.66)
|
||||
general.set_current_view_rotation(-42.05, 0.00, -36.33)
|
||||
|
||||
# Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ class TestRotationModifierOverrides_InstancesRotateWithinRange(EditorTestHelper)
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.run_console("e_WaterOcean=0")
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create vegetation entity and add components
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ class TestRotationModifier_InstancesRotateWithinRange(EditorTestHelper):
|
||||
terrain_texture_resolution=4096,
|
||||
use_terrain=False,
|
||||
)
|
||||
general.run_console("e_WaterOcean=0")
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Set up vegetation entities
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
|
||||
+3
@@ -17,6 +17,7 @@ import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.entity as EntityId
|
||||
import azlmbr.components as components
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
@@ -48,6 +49,8 @@ class TestSlopeFilterFilterStageToggle(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
+2
@@ -103,6 +103,8 @@ class TestExclusiveSurfaceMasksTag(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
|
||||
+2
@@ -104,6 +104,8 @@ class TestInclusiveSurfaceMasksTag(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape"
|
||||
entity_position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice")
|
||||
|
||||
+3
@@ -15,6 +15,7 @@ import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
@@ -52,6 +53,8 @@ class TestSystemSettingsSectorPointDensity(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
+3
@@ -15,6 +15,7 @@ import azlmbr.math as math
|
||||
import azlmbr.paths
|
||||
import azlmbr.editor as editor
|
||||
import azlmbr.bus as bus
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
|
||||
import automatedtesting_shared.hydra_editor_utils as hydra
|
||||
@@ -48,6 +49,8 @@ class TestSystemSettingsSectorSize(EditorTestHelper):
|
||||
use_terrain=False,
|
||||
)
|
||||
|
||||
general.set_current_view_position(512.0, 480.0, 38.0)
|
||||
|
||||
# Create basic vegetation entity
|
||||
position = math.Vector3(512.0, 512.0, 32.0)
|
||||
asset_path = os.path.join("Slices", "PinkFlower.dynamicslice")
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ if(CMAKE_VERSION VERSION_EQUAL 3.19)
|
||||
endif()
|
||||
|
||||
include(cmake/Version.cmake)
|
||||
include(cmake/OutputDirectory.cmake)
|
||||
|
||||
if(NOT PROJECT_NAME)
|
||||
project(O3DE
|
||||
@@ -30,7 +31,7 @@ if(NOT PROJECT_NAME)
|
||||
)
|
||||
endif()
|
||||
|
||||
include(cmake/Initialize.cmake)
|
||||
include(cmake/GeneralSettings.cmake)
|
||||
include(cmake/FileUtil.cmake)
|
||||
include(cmake/PAL.cmake)
|
||||
include(cmake/PALTools.cmake)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <LyShine/ILyShine.h>
|
||||
#include <IRenderer.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
@@ -115,355 +115,4 @@ public: // member functions
|
||||
|
||||
//! Implement virtual destructor just for safety.
|
||||
virtual ~IDraw2d() {}
|
||||
|
||||
//! Start a section of 2D drawing function calls. This will set appropriate render state.
|
||||
//
|
||||
//! \param deferCalls If true then actual render calls are deferred until the end of the frame
|
||||
virtual void BeginDraw2d(bool deferCalls = false) = 0;
|
||||
|
||||
//! Start a section of 2D drawing function calls. This will set appropriate render state.
|
||||
//! This variant allows the viewport size to be specified
|
||||
//
|
||||
//! \param viewportSize The size of the viewport being rendered to
|
||||
//! \param deferCalls If true then actual render calls are deferred until the end of the frame
|
||||
virtual void BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls = false) = 0;
|
||||
|
||||
//! End a section of 2D drawing function calls. This will reset some render state.
|
||||
virtual void EndDraw2d() = 0;
|
||||
|
||||
//! Draw a textured quad with the top left corner at the given position.
|
||||
//
|
||||
//! The image is drawn with the color specified by SetShapeColor and the opacity
|
||||
//! passed as an argument.
|
||||
//! If rotation is non-zero then the quad is rotated. If the pivot point is
|
||||
//! provided then the points of the quad are rotated about that point, otherwise
|
||||
//! they are rotated about the top left corner of the quad.
|
||||
//! \param texId The texture ID returned by ITexture::GetTextureID()
|
||||
//! \param position Position of the top left corner of the quad (before rotation) in pixels
|
||||
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
|
||||
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
|
||||
//! \param opacity The alpha value used when blending
|
||||
//! \param rotation Angle of rotation in degrees counter-clockwise
|
||||
//! \param pivotPoint The point about which the quad is rotated
|
||||
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
|
||||
//! point of the quad and the second is the UV coord of the bottom right point of the quad
|
||||
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
|
||||
virtual void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
|
||||
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr,
|
||||
ImageOptions* imageOptions = nullptr) = 0;
|
||||
|
||||
//! Draw a textured quad where the position specifies the point specified by the alignment.
|
||||
//
|
||||
//! Rotation is always around the position.
|
||||
//! \param texId The texture ID returned by ITexture::GetTextureID()
|
||||
//! \param position Position align point of the quad (before rotation) in pixels
|
||||
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
|
||||
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
|
||||
//! \param horizontalAlignment Specifies how the quad is horizontally aligned to the given position
|
||||
//! \param verticalAlignment Specifies how the quad is vertically aligned to the given position
|
||||
//! \param opacity The alpha value used when blending
|
||||
//! \param rotation Angle of rotation in degrees counter-clockwise
|
||||
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
|
||||
//! point of the quad and the second is the UV coord of the bottom right point of the quad
|
||||
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
|
||||
virtual void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
|
||||
HAlign horizontalAlignment, VAlign verticalAlignment,
|
||||
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr,
|
||||
ImageOptions* imageOptions = nullptr) = 0;
|
||||
|
||||
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
|
||||
//
|
||||
//! \param texId The texture ID returned by ITexture::GetTextureID()
|
||||
//! \param verts An array of 4 vertices, in clockwise order (e.g. top left, top right, bottom right, bottom left)
|
||||
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
|
||||
//! \param pixelRounding Whether and how to round pixel coordinates
|
||||
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
|
||||
virtual void DrawQuad(int texId, VertexPosColUV* verts,
|
||||
int blendMode = UseDefault,
|
||||
Rounding pixelRounding = Rounding::Nearest,
|
||||
int baseState = UseDefault) = 0;
|
||||
|
||||
//! Draw a line
|
||||
//
|
||||
//! \param start The start position
|
||||
//! \param end The end position
|
||||
//! \param color The color of the line
|
||||
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
|
||||
//! \param pixelRounding Whether and how to round pixel coordinates
|
||||
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
|
||||
virtual void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color,
|
||||
int blendMode = UseDefault,
|
||||
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
|
||||
int baseState = UseDefault) = 0;
|
||||
|
||||
//! Draw a line with a texture so it can be dotted or dashed
|
||||
//
|
||||
//! \param texId The texture ID returned by ITexture::GetTextureID()
|
||||
//! \param verts An array of 2 vertices for the start and end points of the line
|
||||
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
|
||||
//! \param pixelRounding Whether and how to round pixel coordinates
|
||||
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
|
||||
virtual void DrawLineTextured(int texId, VertexPosColUV* verts,
|
||||
int blendMode = UseDefault,
|
||||
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
|
||||
int baseState = UseDefault) = 0;
|
||||
|
||||
//! Draw a text string. Only supports ASCII text.
|
||||
//
|
||||
//! The font and effect used to render the text are specified in the textOptions structure
|
||||
//! \param textString A null terminated ASCII text string. May contain \n characters
|
||||
//! \param position Position of the text in pixels. Alignment values in textOptions affect actual position
|
||||
//! \param pointSize The size of the font to use
|
||||
//! \param opacity The opacity (alpha value) to use to draw the text
|
||||
//! \param textOptions Pointer to an options struct. If null the default options are used
|
||||
virtual void DrawText(const char* textString, AZ::Vector2 position, float pointSize,
|
||||
float opacity = 1.0f, TextOptions* textOptions = nullptr) = 0;
|
||||
|
||||
//! Get the width and height (in pixels) that would be used to draw the given text string.
|
||||
//
|
||||
//! Pass the same parameter values that would be used to draw the string
|
||||
virtual AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr) = 0;
|
||||
|
||||
//! Get the width of the rendering viewport (in pixels).
|
||||
//
|
||||
//! If rendering full screen this is the native width from IRenderer
|
||||
virtual float GetViewportWidth() const = 0;
|
||||
|
||||
//! Get the height of the rendering viewport (in pixels).
|
||||
//
|
||||
//! If rendering full screen this is the native width from IRenderer
|
||||
virtual float GetViewportHeight() const = 0;
|
||||
|
||||
//! Get the default values that would be used if no image options were passed in
|
||||
//
|
||||
//! This is a convenient way to initialize the imageOptions struct
|
||||
virtual const ImageOptions& GetDefaultImageOptions() const = 0;
|
||||
|
||||
//! Get the default values that would be used if no text options were passed in
|
||||
//
|
||||
//! This is a convenient way to initialize the textOptions struct
|
||||
virtual const TextOptions& GetDefaultTextOptions() const = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Helper class for using the IDraw2d interface
|
||||
//!
|
||||
//! The Draw2dHelper class is an inline wrapper that provides two convenience features:
|
||||
//! 1. It automatically calls BeginDraw2d/EndDraw2d in its construction/destruction.
|
||||
//! 2. It automatically sets member options structures to their defaults and provides set functions
|
||||
//! to set them.
|
||||
class Draw2dHelper
|
||||
{
|
||||
public: // member functions
|
||||
|
||||
//! Start a section of 2D drawing function calls. This will set appropriate render state.
|
||||
Draw2dHelper(bool deferCalls = false)
|
||||
: m_draw2d(GetDraw2d())
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->BeginDraw2d(deferCalls);
|
||||
m_imageOptions = m_draw2d->GetDefaultImageOptions();
|
||||
m_textOptions = m_draw2d->GetDefaultTextOptions();
|
||||
}
|
||||
}
|
||||
|
||||
//! End a section of 2D drawing function calls. This will reset some render state.
|
||||
~Draw2dHelper()
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->EndDraw2d();
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a textured quad, optional rotation is counter-clockwise in degrees.
|
||||
//
|
||||
//! See IDraw2d:DrawImage for parameter descriptions
|
||||
void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
|
||||
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawImage(texId, position, size, opacity, rotation, pivotPoint, minMaxTexCoords, &m_imageOptions);
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a textured quad where the position specifies the point specified by the alignment.
|
||||
//
|
||||
//! See IDraw2d:DrawImageAligned for parameter descriptions
|
||||
void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
|
||||
IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment,
|
||||
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawImageAligned(texId, position, size, horizontalAlignment, verticalAlignment,
|
||||
opacity, rotation, minMaxTexCoords, &m_imageOptions);
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
|
||||
//
|
||||
//! See IDraw2d:DrawQuad for parameter descriptions
|
||||
void DrawQuad(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
|
||||
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
|
||||
int baseState = IDraw2d::UseDefault)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawQuad(texId, verts, blendMode, pixelRounding, baseState);
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a line
|
||||
//
|
||||
//! See IDraw2d:DrawLine for parameter descriptions
|
||||
void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode = IDraw2d::UseDefault,
|
||||
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
|
||||
int baseState = IDraw2d::UseDefault)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawLine(start, end, color, blendMode, pixelRounding, baseState);
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a line with a texture so it can be dotted or dashed
|
||||
//
|
||||
//! See IDraw2d:DrawLineTextured for parameter descriptions
|
||||
void DrawLineTextured(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
|
||||
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
|
||||
int baseState = IDraw2d::UseDefault)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawLineTextured(texId, verts, blendMode, pixelRounding, baseState);
|
||||
}
|
||||
}
|
||||
|
||||
//! Draw a text string. Only supports ASCII text.
|
||||
//
|
||||
//! See IDraw2d:DrawText for parameter descriptions
|
||||
void DrawText(const char* textString, AZ::Vector2 position, float pointSize, float opacity = 1.0f)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
m_draw2d->DrawText(textString, position, pointSize, opacity, &m_textOptions);
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the width and height (in pixels) that would be used to draw the given text string.
|
||||
//
|
||||
//! See IDraw2d:GetTextSize for parameter descriptions
|
||||
AZ::Vector2 GetTextSize(const char* textString, float pointSize)
|
||||
{
|
||||
if (m_draw2d)
|
||||
{
|
||||
return m_draw2d->GetTextSize(textString, pointSize, &m_textOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
return AZ::Vector2(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// State management
|
||||
|
||||
//! Set the blend mode used for images, default is GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA.
|
||||
void SetImageBlendMode(int mode) { m_imageOptions.blendMode = mode; }
|
||||
|
||||
//! Set the color used for DrawImage and other image drawing.
|
||||
void SetImageColor(AZ::Vector3 color) { m_imageOptions.color = color; }
|
||||
|
||||
//! Set whether images are rounded to have the points on exact pixel boundaries.
|
||||
void SetImagePixelRounding(IDraw2d::Rounding round) { m_imageOptions.pixelRounding = round; }
|
||||
|
||||
//! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST.
|
||||
void SetImageBaseState(int state) { m_imageOptions.baseState = state; }
|
||||
|
||||
//! Set the text font.
|
||||
void SetTextFont(IFFont* font) { m_textOptions.font = font; }
|
||||
|
||||
//! Set the text font effect index.
|
||||
void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; }
|
||||
|
||||
//! Set the text color.
|
||||
void SetTextColor(AZ::Vector3 color) { m_textOptions.color = color; }
|
||||
|
||||
//! Set the text alignment.
|
||||
void SetTextAlignment(IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment)
|
||||
{
|
||||
m_textOptions.horizontalAlignment = horizontalAlignment;
|
||||
m_textOptions.verticalAlignment = verticalAlignment;
|
||||
}
|
||||
|
||||
//! Set a drop shadow for text drawing. An alpha of zero disables drop shadow.
|
||||
void SetTextDropShadow(AZ::Vector2 offset, AZ::Color color)
|
||||
{
|
||||
m_textOptions.dropShadowOffset = offset;
|
||||
m_textOptions.dropShadowColor = color;
|
||||
}
|
||||
|
||||
//! Set a rotation for the text. The text rotates around its position (taking into account alignment).
|
||||
void SetTextRotation(float rotation)
|
||||
{
|
||||
m_textOptions.rotation = rotation;
|
||||
}
|
||||
|
||||
//! Set the base state (that blend mode etc is combined with) used for text, default is GS_NODEPTHTEST.
|
||||
void SetTextBaseState(int state) { m_textOptions.baseState = state; }
|
||||
|
||||
public: // static member functions
|
||||
|
||||
//! Helper to get the IDraw2d interface
|
||||
static IDraw2d* GetDraw2d() { return (gEnv && gEnv->pLyShine) ? gEnv->pLyShine->GetDraw2d() : nullptr; }
|
||||
|
||||
//! Get the width of the rendering viewport (in pixels).
|
||||
static float GetViewportWidth()
|
||||
{
|
||||
IDraw2d* draw2d = GetDraw2d();
|
||||
return (draw2d) ? draw2d->GetViewportWidth() : 0.0f;
|
||||
}
|
||||
|
||||
//! Get the height of the rendering viewport (in pixels).
|
||||
static float GetViewportHeight()
|
||||
{
|
||||
IDraw2d* draw2d = GetDraw2d();
|
||||
return (draw2d) ? draw2d->GetViewportHeight() : 0.0f;
|
||||
}
|
||||
|
||||
//! Round the X and Y coordinates of a point using the given rounding policy
|
||||
template<typename T>
|
||||
static T RoundXY(T value, IDraw2d::Rounding roundingType)
|
||||
{
|
||||
T result = value;
|
||||
|
||||
switch (roundingType)
|
||||
{
|
||||
case IDraw2d::Rounding::None:
|
||||
// nothing to do
|
||||
break;
|
||||
case IDraw2d::Rounding::Nearest:
|
||||
result.SetX(floor(value.GetX() + 0.5f));
|
||||
result.SetY(floor(value.GetY() + 0.5f));
|
||||
break;
|
||||
case IDraw2d::Rounding::Down:
|
||||
result.SetX(floor(value.GetX()));
|
||||
result.SetY(floor(value.GetY()));
|
||||
break;
|
||||
case IDraw2d::Rounding::Up:
|
||||
result.SetX(ceil(value.GetX()));
|
||||
result.SetY(ceil(value.GetY()));
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected: // attributes
|
||||
|
||||
IDraw2d::ImageOptions m_imageOptions; //!< image options are stored locally and updated by member functions
|
||||
IDraw2d::TextOptions m_textOptions; //!< text options are stored locally and updated by member functions
|
||||
IDraw2d* m_draw2d;
|
||||
};
|
||||
|
||||
@@ -1,79 +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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <LyShine/IDraw2d.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Interface used by UI components to render to the canvas
|
||||
//
|
||||
//! The IUiRenderer provides helper functions for UI rendering and also manages state that
|
||||
//! persists between UI elements when rendering a UI canvas.
|
||||
//! For example one UI component can turn on stencil test and that affects all UI rendering
|
||||
//! until it is turned off.
|
||||
//!
|
||||
//! This is a singleton class that is accessed via IUiRenderer::Get() which is a shortcut for
|
||||
//! gEnv->pLyShine()->GetUiRenderer();
|
||||
class IUiRenderer
|
||||
{
|
||||
public: // types
|
||||
|
||||
|
||||
public: // member functions
|
||||
|
||||
//! Implement virtual destructor for safety.
|
||||
virtual ~IUiRenderer() {}
|
||||
|
||||
//! Start the rendering of a UI canvas
|
||||
virtual void BeginCanvasRender(AZ::Vector2 viewportSize) = 0;
|
||||
|
||||
//! End the rendering of a UI canvas
|
||||
virtual void EndCanvasRender() = 0;
|
||||
|
||||
//! Get the current base state
|
||||
virtual int GetBaseState() = 0;
|
||||
|
||||
//! Set the base state
|
||||
virtual void SetBaseState(int state) = 0;
|
||||
|
||||
//! Get the current stencil test reference value
|
||||
virtual uint32 GetStencilRef() = 0;
|
||||
|
||||
//! Set the stencil test reference value
|
||||
virtual void SetStencilRef(uint32) = 0;
|
||||
|
||||
//! Increment the current stencil reference value
|
||||
virtual void IncrementStencilRef() = 0;
|
||||
|
||||
//! Decrement the current stencil reference value
|
||||
virtual void DecrementStencilRef() = 0;
|
||||
|
||||
//! Get flag that indicates we are rendering into a mask. Used to avoid masks on child mask elements.
|
||||
virtual bool IsRenderingToMask() = 0;
|
||||
|
||||
//! Set flag that we are rendering into a mask. Used to avoid masks on child mask elements.
|
||||
virtual void SetIsRenderingToMask(bool isRenderingToMask) = 0;
|
||||
|
||||
//! Push an alpha fade, this is multiplied with any existing alpha fade from parents
|
||||
virtual void PushAlphaFade(float alphaFadeValue) = 0;
|
||||
|
||||
//! Pop an alpha fade off the stack
|
||||
virtual void PopAlphaFade() = 0;
|
||||
|
||||
//! Get the current alpha fade value
|
||||
virtual float GetAlphaFade() const = 0;
|
||||
|
||||
public: // static member functions
|
||||
|
||||
//! Helper function to get the singleton UiRenderer
|
||||
static IUiRenderer* Get() { return gEnv->pLyShine->GetUiRenderer(); }
|
||||
};
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <AzCore/Component/Entity.h>
|
||||
|
||||
#include <LyShine/UiAssetTypes.h>
|
||||
#include <LyShine/UiBase.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -4094,6 +4094,7 @@ void CSystem::CreateSystemVars()
|
||||
"0 = Suppress Asserts\n"
|
||||
"1 = Log Asserts\n"
|
||||
"2 = Show Assert Dialog\n"
|
||||
"3 = Crashes the Application on Assert\n"
|
||||
"Note: when set to '0 = Suppress Asserts', assert expressions are still evaluated. To turn asserts into a no-op, undefine AZ_ENABLE_TRACING and recompile.",
|
||||
OnAssertLevelCvarChanged);
|
||||
CSystem::SetAssertLevel(defaultAssertValue);
|
||||
|
||||
@@ -341,6 +341,16 @@ namespace AZ
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<ComponentApplicationBus>("ComponentApplicationBus")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Components")
|
||||
|
||||
->Event("GetEntityName", &ComponentApplicationBus::Events::GetEntityName)
|
||||
->Event("SetEntityName", &ComponentApplicationBus::Events::SetEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -1050,6 +1060,20 @@ namespace AZ
|
||||
return AZStd::string();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// SetEntityName
|
||||
//=========================================================================
|
||||
bool ComponentApplication::SetEntityName(const EntityId& id, const AZStd::string_view name)
|
||||
{
|
||||
Entity* entity = FindEntity(id);
|
||||
if (entity)
|
||||
{
|
||||
entity->SetName(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// EnumerateEntities
|
||||
//=========================================================================
|
||||
|
||||
@@ -209,6 +209,7 @@ namespace AZ
|
||||
bool DeleteEntity(const EntityId& id) override;
|
||||
Entity* FindEntity(const EntityId& id) override;
|
||||
AZStd::string GetEntityName(const EntityId& id) override;
|
||||
bool SetEntityName(const EntityId& id, const AZStd::string_view name) override;
|
||||
void EnumerateEntities(const ComponentApplicationRequests::EntityCallback& callback) override;
|
||||
ComponentApplication* GetApplication() override { return this; }
|
||||
/// Returns the serialize context that has been registered with the app, if there is one.
|
||||
|
||||
@@ -130,7 +130,13 @@ namespace AZ
|
||||
//! @param entity A reference to the entity whose name you are seeking.
|
||||
//! @return The name of the entity with the specified entity ID.
|
||||
//! If no entity is found for the specified ID, it returns an empty string.
|
||||
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); };
|
||||
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); }
|
||||
|
||||
//! Sets the name of the entity that has the specified entity ID.
|
||||
//! Entity names are not enforced to be unique.
|
||||
//! @param entityId A reference to the entity whose name you want to change.
|
||||
//! @return True if the name was changed successfully, false if it wasn't.
|
||||
virtual bool SetEntityName([[maybe_unused]] const EntityId& id, [[maybe_unused]] const AZStd::string_view name) { return false; }
|
||||
|
||||
//! The type that AZ::ComponentApplicationRequests::EnumerateEntities uses to
|
||||
//! pass entity callbacks to the application for enumeration.
|
||||
|
||||
@@ -63,13 +63,13 @@ namespace AZ
|
||||
static AssetTrackingImpl* GetSharedInstance();
|
||||
static ThreadData& GetSharedThreadData();
|
||||
|
||||
using MasterAssets = AZStd::unordered_map<AssetTrackingId, AssetMasterInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
|
||||
using PrimaryAssets = AZStd::unordered_map<AssetTrackingId, AssetPrimaryInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
|
||||
using ThreadData = ThreadData;
|
||||
using mutex_type = AZStd::mutex;
|
||||
using lock_type = AZStd::lock_guard<mutex_type>;
|
||||
|
||||
mutex_type m_mutex;
|
||||
MasterAssets m_masterAssets;
|
||||
PrimaryAssets m_primaryAssets;
|
||||
AssetTreeNodeBase* m_assetRoot = nullptr;
|
||||
AssetAllocationTableBase* m_allocationTable = nullptr;
|
||||
bool m_performingAnalysis = false;
|
||||
@@ -118,7 +118,7 @@ namespace AZ
|
||||
auto& threadData = GetSharedThreadData();
|
||||
AssetTreeNodeBase* parentAsset = threadData.m_currentAssetStack.empty() ? nullptr : threadData.m_currentAssetStack.back();
|
||||
AssetTreeNodeBase* childAsset;
|
||||
AssetMasterInfo* assetMasterInfo;
|
||||
AssetPrimaryInfo* assetPrimaryInfo;
|
||||
|
||||
if (!parentAsset)
|
||||
{
|
||||
@@ -128,22 +128,22 @@ namespace AZ
|
||||
{
|
||||
lock_type lock(m_mutex);
|
||||
|
||||
// Locate or create the master record for this asset
|
||||
auto masterItr = m_masterAssets.find(assetId);
|
||||
// Locate or create the primary record for this asset
|
||||
auto primaryItr = m_primaryAssets.find(assetId);
|
||||
|
||||
if (masterItr != m_masterAssets.end())
|
||||
if (primaryItr != m_primaryAssets.end())
|
||||
{
|
||||
assetMasterInfo = &masterItr->second;
|
||||
assetPrimaryInfo = &primaryItr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto insertResult = m_masterAssets.emplace(assetId, AssetMasterInfo());
|
||||
assetMasterInfo = &insertResult.first->second;
|
||||
assetMasterInfo->m_id = &insertResult.first->first;
|
||||
auto insertResult = m_primaryAssets.emplace(assetId, AssetPrimaryInfo());
|
||||
assetPrimaryInfo = &insertResult.first->second;
|
||||
assetPrimaryInfo->m_id = &insertResult.first->first;
|
||||
}
|
||||
|
||||
// Add this asset to the stack for this thread's context
|
||||
childAsset = parentAsset->FindOrAddChild(assetId, assetMasterInfo);
|
||||
childAsset = parentAsset->FindOrAddChild(assetId, assetPrimaryInfo);
|
||||
}
|
||||
|
||||
threadData.m_currentAssetStack.push_back(childAsset);
|
||||
@@ -304,7 +304,7 @@ namespace AZ
|
||||
char* pos = buffer;
|
||||
for (auto itr = assetStack.rbegin(); itr != assetStack.rend(); ++itr)
|
||||
{
|
||||
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetMasterInfo()->m_id->m_id.c_str());
|
||||
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetPrimaryInfo()->m_id->m_id.c_str());
|
||||
|
||||
if (pos >= buffer + BUFFER_SIZE)
|
||||
{
|
||||
|
||||
@@ -79,9 +79,9 @@ namespace AZ
|
||||
AssetTrackingString m_id;
|
||||
};
|
||||
|
||||
// Master information about an asset.
|
||||
// Primary information about an asset.
|
||||
// Currently just contains the ID of the asset, but in the future may carry additional information about that asset (such as where in code it was initialized).
|
||||
struct AssetMasterInfo
|
||||
struct AssetPrimaryInfo
|
||||
{
|
||||
const AssetTrackingId* m_id;
|
||||
};
|
||||
@@ -90,8 +90,8 @@ namespace AZ
|
||||
class AssetTreeNodeBase
|
||||
{
|
||||
public:
|
||||
virtual const AssetMasterInfo* GetAssetMasterInfo() const = 0;
|
||||
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) = 0;
|
||||
virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0;
|
||||
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0;
|
||||
};
|
||||
|
||||
// Base class for an asset tree. Implemented by the template AssetTree<>.
|
||||
|
||||
@@ -29,18 +29,18 @@ namespace AZ
|
||||
class AssetTreeNode : public AssetTreeNodeBase
|
||||
{
|
||||
public:
|
||||
AssetTreeNode(const AssetMasterInfo* masterInfo = nullptr, AssetTreeNode* parent = nullptr) :
|
||||
m_masterInfo(masterInfo),
|
||||
AssetTreeNode(const AssetPrimaryInfo* primaryInfo = nullptr, AssetTreeNode* parent = nullptr) :
|
||||
m_primaryinfo(primaryInfo),
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
const AssetMasterInfo* GetAssetMasterInfo() const override
|
||||
const AssetPrimaryInfo* GetAssetPrimaryInfo() const override
|
||||
{
|
||||
return m_masterInfo;
|
||||
return m_primaryinfo;
|
||||
}
|
||||
|
||||
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) override
|
||||
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) override
|
||||
{
|
||||
AssetTreeNodeBase* result = nullptr;
|
||||
auto childItr = m_children.find(id);
|
||||
@@ -61,7 +61,7 @@ namespace AZ
|
||||
|
||||
using AssetMap = AssetTrackingMap<AssetTrackingId, AssetTreeNode>;
|
||||
|
||||
const AssetMasterInfo* m_masterInfo;
|
||||
const AssetPrimaryInfo* m_primaryinfo;
|
||||
AssetTreeNode* m_parent;
|
||||
AssetMap m_children;
|
||||
AssetDataT m_data;
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace AZ
|
||||
static const char* logVerbosityUID = "sys_LogLevel";
|
||||
static const int assertLevel_log = 1;
|
||||
static const int assertLevel_nativeUI = 2;
|
||||
static const int assertLevel_crash = 3;
|
||||
static const int logLevel_errorWarning = 1;
|
||||
static const int logLevel_full = 2;
|
||||
static AZ::EnvironmentVariable<AZStd::unordered_set<size_t>> g_ignoredAsserts;
|
||||
@@ -289,8 +290,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
#if AZ_ENABLE_TRACE_ASSERTS
|
||||
//display native UI dialogs at verbosity level 2 or higher
|
||||
if (currentLevel >= assertLevel_nativeUI)
|
||||
//display native UI dialogs at verbosity level 2
|
||||
if (currentLevel == assertLevel_nativeUI)
|
||||
{
|
||||
AZ::NativeUI::AssertAction buttonResult;
|
||||
EBUS_EVENT_RESULT(buttonResult, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, dialogBoxText);
|
||||
@@ -314,7 +315,13 @@ namespace AZ
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif //AZ_ENABLE_TRACE_ASSERTS
|
||||
// Crash the application directly at assert level 3
|
||||
if (currentLevel >= assertLevel_crash)
|
||||
{
|
||||
AZ_Crash();
|
||||
}
|
||||
}
|
||||
g_alreadyHandlingAssertOrFatal = false;
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ namespace AZ
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("GetTranslated", &Aabb::GetTranslated)
|
||||
->Method("GetSurfaceArea", &Aabb::GetSurfaceArea)
|
||||
->Method("GetTransformedObb", &Aabb::GetTransformedObb)
|
||||
->Method("GetTransformedAabb", &Aabb::GetTransformedAabb)
|
||||
->Method("GetTransformedObb", static_cast<Obb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedObb))
|
||||
->Method("GetTransformedAabb", static_cast<Aabb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedAabb))
|
||||
->Method("ApplyTransform", &Aabb::ApplyTransform)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; })
|
||||
@@ -195,6 +195,20 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Matrix3x4 matrixNoScale = matrix3x4;
|
||||
const AZ::Vector3 scale = matrixNoScale.ExtractScale();
|
||||
const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale);
|
||||
|
||||
return Obb::CreateFromPositionRotationAndHalfLengths(
|
||||
matrix3x4 * GetCenter(),
|
||||
rotation,
|
||||
0.5f * scale * GetExtents()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyTransform(const Transform& transform)
|
||||
{
|
||||
Vector3 a, b, axisCoeffs;
|
||||
@@ -224,4 +238,17 @@ namespace AZ
|
||||
m_min = newMin;
|
||||
m_max = newMax;
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4)
|
||||
{
|
||||
const AZ::Vector3 extents = GetExtents();
|
||||
const AZ::Vector3 center = matrix3x4 * GetCenter();
|
||||
AZ::Vector3 newHalfExtents(
|
||||
0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents));
|
||||
m_min = center - newHalfExtents;
|
||||
m_max = center + newHalfExtents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +129,21 @@ namespace AZ
|
||||
|
||||
void ApplyTransform(const Transform& transform);
|
||||
|
||||
void ApplyMatrix3x4(const Matrix3x4& matrix3x4);
|
||||
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
class Obb GetTransformedObb(const Transform& transform) const;
|
||||
[[nodiscard]] Obb GetTransformedObb(const Transform& transform) const;
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
[[nodiscard]] Obb GetTransformedObb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Checks if this aabb is equal to another within a floating point tolerance.
|
||||
bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const;
|
||||
|
||||
@@ -292,6 +292,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Aabb::MultiplyByScale(const Vector3& scale)
|
||||
{
|
||||
m_min *= scale;
|
||||
m_max *= scale;
|
||||
AZ_MATH_ASSERT(IsValid(), "Min must be less than Max");
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Transform& transform) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
@@ -300,6 +308,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
aabb.ApplyMatrix3x4(matrix3x4);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const
|
||||
{
|
||||
return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance);
|
||||
|
||||
@@ -258,7 +258,8 @@ namespace AZ
|
||||
Method("CreateFromMatrix3x3", &Quaternion::CreateFromMatrix3x3)->
|
||||
Method("CreateFromMatrix4x4", &Quaternion::CreateFromMatrix4x4)->
|
||||
Method("CreateFromAxisAngle", &Quaternion::CreateFromAxisAngle)->
|
||||
Method("CreateShortestArc", &Quaternion::CreateShortestArc)
|
||||
Method("CreateShortestArc", &Quaternion::CreateShortestArc)->
|
||||
Method("CreateFromEulerAnglesDegrees", &Quaternion::CreateFromEulerAnglesDegrees)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +250,7 @@ namespace AZ
|
||||
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
|
||||
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
|
||||
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::TransformDefaultConstructor)->
|
||||
Constructor<const Vector3&, const Quaternion&, const Vector3&>()->
|
||||
Method("GetBasis", &Transform::GetBasis)->
|
||||
Method("GetBasisX", &Transform::GetBasisX)->
|
||||
Method("GetBasisY", &Transform::GetBasisY)->
|
||||
|
||||
@@ -40,14 +40,13 @@ ly_add_target(
|
||||
${common_dir}
|
||||
${AZ_CORE_RADTELEMETRY_INCLUDE_DIRECTORIES}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
3rdParty::cityhash
|
||||
PUBLIC
|
||||
3rdParty::Lua
|
||||
3rdParty::RapidJSON
|
||||
3rdParty::RapidXML
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
3rdParty::cityhash
|
||||
${AZ_CORE_RADTELEMETRY_BUILD_DEPENDENCIES}
|
||||
)
|
||||
ly_add_source_properties(
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(&rootAsset, &m_env->m_tree.GetRoot());
|
||||
ASSERT_NE(itr, rootAsset.m_children.end());
|
||||
EXPECT_EQ(itr->second.m_masterInfo->m_id->m_id, "TestScopedAllocation.1");
|
||||
EXPECT_EQ(itr->second.m_primaryinfo->m_id->m_id, "TestScopedAllocation.1");
|
||||
|
||||
EXPECT_EQ(&itr->second, m_env->m_table.FindAllocation(TEST_POINTER));
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
@@ -385,4 +386,77 @@ namespace UnitTest
|
||||
EXPECT_TRUE(aabb.GetMin().IsClose(transAabb.GetMin()));
|
||||
EXPECT_TRUE(aabb.GetMax().IsClose(transAabb.GetMax()));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedObbMatrix3x4)
|
||||
{
|
||||
Vector3 min(-1.0f, -2.0f, -3.0f);
|
||||
Vector3 max(4.0f, 3.0f, 2.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.46f, 0.26f, 0.58f, 0.62f);
|
||||
Vector3 translation(5.0f, 7.0f, 9.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(0.5f, 1.5f, 2.0f));
|
||||
|
||||
Obb obb = aabb.GetTransformedObb(matrix3x4);
|
||||
|
||||
EXPECT_THAT(obb.GetRotation(), IsClose(rotation));
|
||||
EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.25f, 3.75f, 5.0f)));
|
||||
EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.928f, 7.9156f, 9.3708f)));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedAabbMatrix3x4)
|
||||
{
|
||||
Vector3 min(2.0f, 3.0f, 5.0f);
|
||||
Vector3 max(6.0f, 5.0f, 11.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.34f, 0.46f, 0.58f, 0.58f);
|
||||
Vector3 translation(-3.0f, -4.0f, -5.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(1.2f, 0.8f, 2.0f));
|
||||
|
||||
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
|
||||
|
||||
EXPECT_THAT(transformedAabb.GetMin(), IsClose(Vector3(4.1488f, -0.01216f, -0.31904f)));
|
||||
EXPECT_THAT(transformedAabb.GetMax(), IsClose(Vector3(16.3216f, 6.54272f, 5.98112f)));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, GetTransformedObbFitsInsideTransformedAabb)
|
||||
{
|
||||
Vector3 min(4.0f, 3.0f, 1.0f);
|
||||
Vector3 max(7.0f, 6.0f, 8.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Quaternion rotation(0.40f, 0.40f, 0.64f, 0.52f);
|
||||
Vector3 translation(-2.0f, 4.0f, -3.0f);
|
||||
|
||||
Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
|
||||
matrix3x4.MultiplyByScale(Vector3(2.2f, 0.6f, 1.4f));
|
||||
|
||||
Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4);
|
||||
Obb transformedObb = aabb.GetTransformedObb(matrix3x4);
|
||||
Aabb aabbContainingTransformedObb = Aabb::CreateFromObb(transformedObb);
|
||||
|
||||
EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin()));
|
||||
EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax()));
|
||||
}
|
||||
|
||||
TEST(MATH_AabbTransform, MultiplyByScale)
|
||||
{
|
||||
Vector3 min(2.0f, 6.0f, 8.0f);
|
||||
Vector3 max(6.0f, 9.0f, 10.0f);
|
||||
Aabb aabb = Aabb::CreateFromMinMax(min, max);
|
||||
|
||||
Vector3 scale(0.5f, 2.0f, 1.5f);
|
||||
aabb.MultiplyByScale(scale);
|
||||
|
||||
EXPECT_THAT(aabb.GetMin(), IsClose(Vector3(1.0f, 12.0f, 12.0f)));
|
||||
EXPECT_THAT(aabb.GetMax(), IsClose(Vector3(3.0f, 18.0f, 15.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Physics
|
||||
class CharacterColliderNodeConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
|
||||
AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
virtual ~CharacterColliderNodeConfiguration() = default;
|
||||
@@ -42,7 +42,7 @@ namespace Physics
|
||||
class CharacterColliderConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
|
||||
AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
virtual ~CharacterColliderConfiguration() = default;
|
||||
@@ -63,21 +63,23 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
|
||||
AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
|
||||
|
||||
virtual ~CharacterConfiguration() = default;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with.
|
||||
AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on.
|
||||
MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character.
|
||||
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior.
|
||||
float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees.
|
||||
float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb.
|
||||
float m_minimumMovementDistance = 0.001f; ///< To avoid jittering, the controller will not attempt to move distances below this.
|
||||
float m_maximumSpeed = 100.0f; ///< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
|
||||
AZStd::string m_colliderTag; ///< Used to identify the collider associated with the character controller.
|
||||
AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with.
|
||||
AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on.
|
||||
MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character.
|
||||
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior.
|
||||
float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees.
|
||||
float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb.
|
||||
float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this.
|
||||
float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
|
||||
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller.
|
||||
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
|
||||
};
|
||||
|
||||
/// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready
|
||||
@@ -88,7 +90,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
|
||||
AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
|
||||
|
||||
~Character() override = default;
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ namespace AzPhysics
|
||||
struct SimulatedBodyConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
|
||||
AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SimulatedBodyConfiguration() = default;
|
||||
|
||||
@@ -246,26 +246,6 @@ namespace Physics
|
||||
using SystemRequests = System;
|
||||
using SystemRequestBus = AZ::EBus<SystemRequests, SystemRequestsTraits>;
|
||||
|
||||
/// Physics character system global requests.
|
||||
class CharacterSystemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// EBusTraits
|
||||
// singleton pattern
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
virtual ~CharacterSystemRequests() = default;
|
||||
|
||||
/// Creates the physics representation used to handle basic character interactions (also known as a character
|
||||
/// controller).
|
||||
virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig,
|
||||
const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0;
|
||||
};
|
||||
|
||||
typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus;
|
||||
|
||||
/// Physics system global debug requests.
|
||||
class SystemDebugRequests
|
||||
: public AZ::EBusTraits
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace AzFramework
|
||||
|
||||
// ViewportControllerInterface ...
|
||||
bool HandleInputChannelEvent(const ViewportControllerInputEvent& event) override;
|
||||
void ResetInputChannels() override;
|
||||
void UpdateViewport(const ViewportControllerUpdateEvent& event) override;
|
||||
void RegisterViewportContext(ViewportId viewport) override;
|
||||
void UnregisterViewportContext(ViewportId viewport) override;
|
||||
@@ -58,6 +59,7 @@ namespace AzFramework
|
||||
ViewportId GetViewportId() const { return m_viewportId; }
|
||||
|
||||
virtual bool HandleInputChannelEvent([[maybe_unused]]const ViewportControllerInputEvent& event) { return false; }
|
||||
virtual void ResetInputChannels() {}
|
||||
virtual void UpdateViewport([[maybe_unused]]const ViewportControllerUpdateEvent& event) {}
|
||||
|
||||
private:
|
||||
|
||||
@@ -30,6 +30,15 @@ namespace AzFramework
|
||||
return instanceIt->second->HandleInputChannelEvent(event);
|
||||
}
|
||||
|
||||
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
|
||||
void MultiViewportController<TViewportControllerInstance, Priority>::ResetInputChannels()
|
||||
{
|
||||
for (auto instanceIt = m_instances.begin(); instanceIt != m_instances.end(); ++instanceIt)
|
||||
{
|
||||
instanceIt->second->ResetInputChannels();
|
||||
}
|
||||
}
|
||||
|
||||
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
|
||||
void MultiViewportController<TViewportControllerInstance, Priority>::UpdateViewport(const ViewportControllerUpdateEvent& event)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,11 @@ namespace AzFramework
|
||||
|
||||
bool ViewportControllerList::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If our event priority is "custom", we should dispatch at all priority levels in order
|
||||
using AzFramework::ViewportControllerPriority;
|
||||
if (event.m_priority == AzFramework::ViewportControllerPriority::DispatchToAllPriorities)
|
||||
@@ -76,6 +81,23 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportControllerList::ResetInputChannels()
|
||||
{
|
||||
// We don't need to send this while we're disabled, we're guaranteed to call ResetInputChannels after being re-enabled.
|
||||
if (!IsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& controllerList : m_controllers)
|
||||
{
|
||||
for (const auto& controller : controllerList.second)
|
||||
{
|
||||
controller->ResetInputChannels();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewportControllerList::DispatchInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
|
||||
{
|
||||
if (auto priorityListIt = m_controllers.find(event.m_priority); priorityListIt != m_controllers.end())
|
||||
@@ -106,6 +128,11 @@ namespace AzFramework
|
||||
|
||||
void ViewportControllerList::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
|
||||
{
|
||||
if (!IsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If our event priority is "custom", we should dispatch at all priority levels in reverse order
|
||||
// Reverse order lets high priority controllers get the last say in viewport update operations
|
||||
using AzFramework::ViewportControllerPriority;
|
||||
@@ -174,4 +201,22 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewportControllerList::IsEnabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void ViewportControllerList::SetEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled != enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
// If we've been re-enabled, reset our input channels as they may have missed state changes.
|
||||
if (m_enabled)
|
||||
{
|
||||
ResetInputChannels();
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace AzFramework
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace AzFramework
|
||||
//! either a controller returns true to consume the event in OnInputChannelEvent or the controller list is exhausted.
|
||||
//! InputChannelEvents are sent to controllers in priority order (from the lowest priority value to the highest).
|
||||
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
|
||||
//! Dispatches a ResetInputChannels call to all controllers registered to this list.
|
||||
//! Calls to controllers are made in an undefined order.
|
||||
void ResetInputChannels() override;
|
||||
//! Dispatches an update tick to all controllers registered to this list.
|
||||
//! This occurs in *reverse* priority order (i.e. from the highest priority value to the lowest) so that
|
||||
//! controllers with the highest registration priority may override the transforms of the controllers with the
|
||||
@@ -50,6 +53,12 @@ namespace AzFramework
|
||||
//! All ViewportControllerLists have a priority of Custom to ensure
|
||||
//! that they receive events at all priorities from any parent controllers.
|
||||
AzFramework::ViewportControllerPriority GetPriority() const { return ViewportControllerPriority::DispatchToAllPriorities; }
|
||||
//! Returns true if this controller list is enabled, i.e.
|
||||
//! it is accepting and forwarding input and update events to its children.
|
||||
bool IsEnabled() const;
|
||||
//! Set this controller list's enabled state.
|
||||
//! If a controller list is disabled, it will ignore all input and update events rather than dispatching them to its children.
|
||||
void SetEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
void SortControllers();
|
||||
@@ -58,5 +67,6 @@ namespace AzFramework
|
||||
|
||||
AZStd::unordered_map<AzFramework::ViewportControllerPriority, AZStd::vector<ViewportControllerPtr>> m_controllers;
|
||||
AZStd::unordered_set<ViewportId> m_viewports;
|
||||
bool m_enabled = true;
|
||||
};
|
||||
} //namespace AzFramework
|
||||
|
||||
@@ -33,12 +33,12 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzCore
|
||||
PUBLIC
|
||||
AZ::GridMate
|
||||
3rdParty::md5
|
||||
3rdParty::zlib
|
||||
3rdParty::zstd
|
||||
3rdParty::lz4
|
||||
PUBLIC
|
||||
AZ::GridMate
|
||||
)
|
||||
|
||||
if(LY_ENABLE_STATISTICAL_PROFILING)
|
||||
|
||||
+14
-3
@@ -29,6 +29,20 @@ namespace AzFramework::AssetSystem::Platform
|
||||
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
|
||||
AZStd::string_view projectPath)
|
||||
{
|
||||
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
|
||||
assetProcessorPath /= "AssetProcessor";
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
|
||||
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor";
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pid_t firstChildPid = fork();
|
||||
if (firstChildPid == 0)
|
||||
{
|
||||
@@ -47,9 +61,6 @@ namespace AzFramework::AssetSystem::Platform
|
||||
pid_t secondChildPid = fork();
|
||||
if (secondChildPid == 0)
|
||||
{
|
||||
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
|
||||
assetProcessorPath /= "AssetProcessor";
|
||||
|
||||
AZStd::array args {
|
||||
assetProcessorPath.c_str(), assetProcessorPath.c_str(), "--start-hidden",
|
||||
static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), static_cast<const char*>(nullptr)
|
||||
|
||||
+13
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -20,6 +21,7 @@ namespace AzFramework::AssetSystem::Platform
|
||||
{
|
||||
void AllowAssetProcessorToForeground()
|
||||
{}
|
||||
|
||||
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
|
||||
AZStd::string_view projectPath)
|
||||
{
|
||||
@@ -29,6 +31,17 @@ namespace AzFramework::AssetSystem::Platform
|
||||
assetProcessorPath /= "../../../AssetProcessor.app";
|
||||
assetProcessorPath = assetProcessorPath.LexicallyNormal();
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
|
||||
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app";
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str());
|
||||
// Add the engine path to the launch command if not empty
|
||||
if (!engineRoot.empty())
|
||||
|
||||
+12
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
#include <Psapi.h>
|
||||
@@ -67,6 +68,17 @@ namespace AzFramework::AssetSystem::Platform
|
||||
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
|
||||
assetProcessorPath /= "AssetProcessor.exe";
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
|
||||
assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.exe";
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"("%s" --start-hidden)", assetProcessorPath.c_str());
|
||||
|
||||
// Add the engine path to the launch command if not empty
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <AzCore/std/typetraits/is_enum.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/Name/NameDictionary.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
@@ -173,6 +175,22 @@ namespace AzNetworking
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SerializeObjectHelper<AZ::Name>
|
||||
{
|
||||
static bool SerializeObject(ISerializer& serializer, AZ::Name& value)
|
||||
{
|
||||
AZ::Name::Hash nameHash = value.GetHash();
|
||||
bool result = serializer.Serialize(nameHash, "NameHash");
|
||||
|
||||
if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject)
|
||||
{
|
||||
value = AZ::NameDictionary::Instance().FindName(nameHash);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include <AzNetworking/Serialization/AzContainerSerializers.h>
|
||||
|
||||
@@ -2298,6 +2298,12 @@ namespace AzQtComponents
|
||||
OptimizedSetParent(dock, mainWindow);
|
||||
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock);
|
||||
dock->show();
|
||||
|
||||
// Make sure we listen for events on the dock widget being put into a floating dock window
|
||||
// because this might be called programmatically, so the dock widget might have never been
|
||||
// parented to our m_mainWindow initially, so it won't already have an event filter,
|
||||
// which will prevent the docking functionality from working.
|
||||
dock->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -815,8 +815,6 @@ namespace AzToolsFramework
|
||||
/// Hide or show the circular dependency error when saving slices
|
||||
virtual void SetShowCircularDependencyError(const bool& /*showCircularDependencyError*/) {}
|
||||
|
||||
virtual void SetEditTool(const char* /*tool*/) {}
|
||||
|
||||
/// Launches the Lua editor and opens the specified (space separated) files.
|
||||
virtual void LaunchLuaEditor(const char* /*files*/) {}
|
||||
|
||||
|
||||
@@ -170,6 +170,15 @@ namespace AzToolsFramework
|
||||
return m_filter;
|
||||
}
|
||||
|
||||
QSharedPointer<CompositeFilter> SearchWidget::GetStringFilter() const
|
||||
{
|
||||
return m_stringFilter;
|
||||
}
|
||||
|
||||
QSharedPointer<CompositeFilter> SearchWidget::GetTypesFilter() const
|
||||
{
|
||||
return m_typesFilter;
|
||||
}
|
||||
} // namespace AssetBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ namespace AzToolsFramework
|
||||
|
||||
QSharedPointer<CompositeFilter> GetFilter() const;
|
||||
|
||||
QSharedPointer<CompositeFilter> GetStringFilter() const;
|
||||
|
||||
QSharedPointer<CompositeFilter> GetTypesFilter() const;
|
||||
|
||||
QString GetFilterString() const { return textFilter(); }
|
||||
void ClearStringFilter() { ClearTextFilter(); }
|
||||
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ namespace AzToolsFramework
|
||||
else
|
||||
{
|
||||
QPixmap pixmap = thumbnail->GetPixmap(size);
|
||||
painter->drawPixmap(point.x(), point.y(), size.width(), size.height(), pixmap);
|
||||
painter->drawPixmap(point, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
return m_iconSize;
|
||||
}
|
||||
|
||||
+8
-2
@@ -491,6 +491,14 @@ namespace AzToolsFramework
|
||||
|
||||
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditorBegin);
|
||||
|
||||
//cache the current selected entities.
|
||||
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
|
||||
//deselect entities if selected when entering game mode before deactivating the entities in StartPlayInEditor(...)
|
||||
if (!m_selectedBeforeStartingGame.empty())
|
||||
{
|
||||
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::MarkEntitiesDeselected, m_selectedBeforeStartingGame);
|
||||
}
|
||||
|
||||
if (m_isLegacySliceService)
|
||||
{
|
||||
SliceEditorEntityOwnershipService* editorEntityOwnershipService =
|
||||
@@ -507,8 +515,6 @@ namespace AzToolsFramework
|
||||
|
||||
m_isRunningGame = true;
|
||||
|
||||
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
|
||||
|
||||
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditor);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -94,6 +94,7 @@ namespace AzToolsFramework
|
||||
m_prefabSystemComponent->RemoveTemplate(templateId);
|
||||
}
|
||||
m_rootInstance->Reset();
|
||||
m_rootInstance->SetContainerEntityName("Level");
|
||||
|
||||
AzFramework::EntityOwnershipServiceNotificationBus::Event(
|
||||
m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset);
|
||||
@@ -198,6 +199,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_rootInstance->SetTemplateId(templateId);
|
||||
m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename));
|
||||
m_rootInstance->SetContainerEntityName("Level");
|
||||
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -123,7 +123,11 @@ namespace AzToolsFramework
|
||||
void Instance::SetTemplateSourcePath(AZ::IO::PathView sourcePath)
|
||||
{
|
||||
m_templateSourcePath = sourcePath;
|
||||
m_containerEntity->SetName(sourcePath.Filename().Native());
|
||||
}
|
||||
|
||||
void Instance::SetContainerEntityName(AZStd::string_view containerName)
|
||||
{
|
||||
m_containerEntity->SetName(containerName);
|
||||
}
|
||||
|
||||
bool Instance::AddEntity(AZ::Entity& entity)
|
||||
@@ -570,7 +574,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZ::EntityId Instance::GetContainerEntityId() const
|
||||
{
|
||||
return m_containerEntity->GetId();
|
||||
return m_containerEntity ? m_containerEntity->GetId() : AZ::EntityId();
|
||||
}
|
||||
|
||||
bool Instance::HasContainerEntity() const
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace AzToolsFramework
|
||||
|
||||
const AZ::IO::Path& GetTemplateSourcePath() const;
|
||||
void SetTemplateSourcePath(AZ::IO::PathView sourcePath);
|
||||
void SetContainerEntityName(AZStd::string_view containerName);
|
||||
|
||||
bool AddEntity(AZ::Entity& entity);
|
||||
bool AddEntity(AZ::Entity& entity, EntityAlias entityAlias);
|
||||
|
||||
@@ -709,7 +709,7 @@ namespace AzToolsFramework
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entity->GetId());
|
||||
AZ_Assert(
|
||||
owningInstance.has_value(),
|
||||
"An error occored while retrieving entities and prefab instances : "
|
||||
"An error occurred while retrieving entities and prefab instances : "
|
||||
"Owning instance of entity with id '%llu' couldn't be found",
|
||||
entity->GetId());
|
||||
|
||||
@@ -793,7 +793,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_Assert(
|
||||
false,
|
||||
"An error occored in function EntitiesBelongToSameInstance: "
|
||||
"An error occurred in function EntitiesBelongToSameInstance: "
|
||||
"Owning instance of entity with id '%llu' couldn't be found",
|
||||
entityId);
|
||||
return false;
|
||||
|
||||
@@ -122,6 +122,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
newInstance->SetTemplateSourcePath(relativeFilePath);
|
||||
newInstance->SetContainerEntityName(relativeFilePath.Stem().Native());
|
||||
|
||||
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance, shouldCreateLinks);
|
||||
if (newTemplateId == InvalidTemplateId)
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h>
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
AZ_PUSH_DISABLE_WARNING(4127 4251 4800 4244, "-Wunknown-warning-option") // 4127: conditional expression is constant
|
||||
// 4251: 'QTextCodec::ConverterState::flags': class 'QFlags<QTextCodec::ConversionFlag>' needs to have dll-interface to be used by clients of struct 'QTextCodec::ConverterState'
|
||||
// 4800: 'QTextBoundaryFinderPrivate *const ': forcing value to bool 'true' or 'false' (performance warning)
|
||||
// 4244: conversion from 'int' to 'qint8', possible loss of data
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QThreadPool>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AzToolsFramework
|
||||
@@ -80,7 +82,11 @@ namespace AzToolsFramework
|
||||
if (m_state == State::Unloaded)
|
||||
{
|
||||
m_state = State::Loading;
|
||||
QFuture<void> future = QtConcurrent::run([this](){ LoadThread(); });
|
||||
QThreadPool* threadPool;
|
||||
ThumbnailContextRequestBus::BroadcastResult(
|
||||
threadPool,
|
||||
&ThumbnailContextRequestBus::Handler::GetThreadPool);
|
||||
QFuture<void> future = QtConcurrent::run(threadPool, [this](){ LoadThread(); });
|
||||
m_watcher.setFuture(future);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,15 @@ namespace AzToolsFramework
|
||||
: m_missingThumbnail(new MissingThumbnail(thumbnailSize))
|
||||
, m_loadingThumbnail(new LoadingThumbnail(thumbnailSize))
|
||||
, m_thumbnailSize(thumbnailSize)
|
||||
, m_threadPool(this)
|
||||
{
|
||||
ThumbnailContextRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
ThumbnailContext::~ThumbnailContext() = default;
|
||||
ThumbnailContext::~ThumbnailContext()
|
||||
{
|
||||
ThumbnailContextRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
bool ThumbnailContext::IsLoading(SharedThumbnailKey key)
|
||||
{
|
||||
@@ -53,6 +58,11 @@ namespace AzToolsFramework
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetBrowserViewRequests::Update);
|
||||
}
|
||||
|
||||
QThreadPool* ThumbnailContext::GetThreadPool()
|
||||
{
|
||||
return &m_threadPool;
|
||||
}
|
||||
|
||||
SharedThumbnail ThumbnailContext::GetThumbnail(SharedThumbnailKey key)
|
||||
{
|
||||
SharedThumbnail thumbnail;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QThreadPool>
|
||||
#endif
|
||||
|
||||
class QString;
|
||||
@@ -40,6 +41,7 @@ namespace AzToolsFramework
|
||||
*/
|
||||
class ThumbnailContext
|
||||
: public QObject
|
||||
, public ThumbnailContextRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -58,10 +60,13 @@ namespace AzToolsFramework
|
||||
void UnregisterThumbnailProvider(const char* providerName);
|
||||
|
||||
void RedrawThumbnail();
|
||||
|
||||
|
||||
//! Default context used for most thumbnails
|
||||
static constexpr const char* DefaultContext = "Default";
|
||||
|
||||
// ThumbnailContextRequestBus::Handler interface overrides...
|
||||
QThreadPool* GetThreadPool() override;
|
||||
|
||||
private:
|
||||
struct ProviderCompare {
|
||||
bool operator() (const SharedThumbnailProvider& lhs, const SharedThumbnailProvider& rhs) const
|
||||
@@ -79,6 +84,9 @@ namespace AzToolsFramework
|
||||
SharedThumbnail m_loadingThumbnail;
|
||||
//! Thumbnail size (width and height in pixels)
|
||||
int m_thumbnailSize;
|
||||
//! There is only a limited number of threads on global threadPool, because there can be many thumbnails rendering at once
|
||||
//! an individual threadPool is needed to avoid deadlocks
|
||||
QThreadPool m_threadPool;
|
||||
};
|
||||
} // namespace Thumbnailer
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -79,7 +79,12 @@ namespace AzToolsFramework
|
||||
int realHeight = qMin(aznumeric_cast<int>(originalWidth /aspectRatio), originalHeight);
|
||||
int realWidth = aznumeric_cast<int>(realHeight * aspectRatio);
|
||||
int x = (originalWidth - realWidth) / 2;
|
||||
painter.drawPixmap(QRect(x, 0, realHeight, realWidth), pixmap);
|
||||
// pixmap needs to be manually scaled to produce smoother result and avoid looking pixelated
|
||||
// using painter.setRenderHint(QPainter::SmoothPixmapTransform); does not seem to work
|
||||
// Note: there is a potential issue with pixmap.scaled:
|
||||
// it is multithreaded (using global threadPool) and blocking until finished.
|
||||
// A deadlock will happen if global threadPool has no free threads available.
|
||||
painter.drawPixmap(QPoint(x, 0), pixmap.scaled(realWidth, realHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,23 @@
|
||||
#include <AzToolsFramework/Thumbnails/Thumbnail.h>
|
||||
|
||||
class QPixmap;
|
||||
class QThreadPool;
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Thumbnailer
|
||||
{
|
||||
//! Interaction with thumbnail context
|
||||
class ThumbnailContextRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//! Get thread pool for drawing thumbnails
|
||||
virtual QThreadPool* GetThreadPool() = 0;
|
||||
};
|
||||
|
||||
using ThumbnailContextRequestBus = AZ::EBus<ThumbnailContextRequests>;
|
||||
|
||||
//! Interaction with thumbnailer
|
||||
class ThumbnailerRequests
|
||||
: public AZ::EBusTraits
|
||||
|
||||
+5
@@ -61,6 +61,11 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorEntityUiHandlerBase::CanRename(AZ::EntityId /*entityId*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditorEntityUiHandlerBase::PaintItemBackground(QPainter* /*painter*/, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
|
||||
{
|
||||
}
|
||||
|
||||
+2
@@ -47,6 +47,8 @@ namespace AzToolsFramework
|
||||
virtual QPixmap GenerateItemIcon(AZ::EntityId entityId) const;
|
||||
//! Returns whether the element's lock and visibility state should be accessible in the Outliner
|
||||
virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const;
|
||||
//! Returns whether the element's name should be editable
|
||||
virtual bool CanRename(AZ::EntityId entityId) const;
|
||||
|
||||
//! Paints the background of the item in the Outliner.
|
||||
virtual void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
+4
@@ -192,6 +192,10 @@ namespace LegacyFramework
|
||||
// if we're in console mode, listen for CTRL+C
|
||||
::SetConsoleCtrlHandler(CTRL_BREAK_HandlerRoutine, true);
|
||||
#endif
|
||||
|
||||
m_ptrCommandLineParser = aznew AzFramework::CommandLine();
|
||||
m_ptrCommandLineParser->Parse(m_desc.m_argc, m_desc.m_argv);
|
||||
|
||||
// If we don't have one create a serialize context
|
||||
if (GetSerializeContext() == nullptr)
|
||||
{
|
||||
|
||||
+25
-24
@@ -945,6 +945,12 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable reparenting to the root level
|
||||
if (!newParentId.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore entities not owned by the editor context. It is assumed that all entities belong
|
||||
// to the same context since multiple selection doesn't span across views.
|
||||
for (const AZ::EntityId& entityId : selectedEntityIds)
|
||||
@@ -974,39 +980,33 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (newParentId.IsValid())
|
||||
bool isLayerEntity = false;
|
||||
Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
isLayerEntity,
|
||||
entityId,
|
||||
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
// Layers can only have other layers as parents, or have no parent.
|
||||
if (isLayerEntity)
|
||||
{
|
||||
bool isLayerEntity = false;
|
||||
bool newParentIsLayer = false;
|
||||
Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
isLayerEntity,
|
||||
entityId,
|
||||
newParentIsLayer,
|
||||
newParentId,
|
||||
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
// Layers can only have other layers as parents, or have no parent.
|
||||
if (isLayerEntity)
|
||||
if (!newParentIsLayer)
|
||||
{
|
||||
bool newParentIsLayer = false;
|
||||
Layers::EditorLayerComponentRequestBus::EventResult(
|
||||
newParentIsLayer,
|
||||
newParentId,
|
||||
&Layers::EditorLayerComponentRequestBus::Events::HasLayer);
|
||||
if (!newParentIsLayer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Only check the entity pointer if the entity id is valid because
|
||||
//we want to allow dragging items to unoccupied parts of the tree to un-parent them
|
||||
if (newParentId.IsValid())
|
||||
AZ::Entity* newParentEntity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(newParentEntity, &AZ::ComponentApplicationRequests::FindEntity, newParentId);
|
||||
if (!newParentEntity)
|
||||
{
|
||||
AZ::Entity* newParentEntity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(newParentEntity, &AZ::ComponentApplicationRequests::FindEntity, newParentId);
|
||||
if (!newParentEntity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//reject dragging on to yourself or your children
|
||||
@@ -1344,14 +1344,15 @@ namespace AzToolsFramework
|
||||
emit EnableSelectionUpdates(false);
|
||||
auto parentIndex = GetIndexFromEntity(parentId);
|
||||
auto childIndex = GetIndexFromEntity(childId);
|
||||
beginRemoveRows(parentIndex, childIndex.row(), childIndex.row());
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void EntityOutlinerListModel::OnEntityInfoUpdatedRemoveChildEnd(AZ::EntityId parentId, AZ::EntityId childId)
|
||||
{
|
||||
(void)childId;
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
endRemoveRows();
|
||||
|
||||
endResetModel();
|
||||
|
||||
//must refresh partial lock/visibility of parents
|
||||
m_isFilterDirty = true;
|
||||
|
||||
+24
-5
@@ -30,6 +30,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx>
|
||||
#include <AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerDisplayOptionsMenu.h>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx>
|
||||
#include <AzToolsFramework/UI/Outliner/EntityOutlinerSortFilterProxyModel.hxx>
|
||||
@@ -271,6 +272,12 @@ namespace AzToolsFramework
|
||||
|
||||
m_listModel->Initialize();
|
||||
|
||||
m_editorEntityUiInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
|
||||
AZ_Assert(
|
||||
m_editorEntityUiInterface != nullptr,
|
||||
"EntityOutlinerWidget requires a EditorEntityUiInterface instance on Initialize.");
|
||||
|
||||
EditorPickModeNotificationBus::Handler::BusConnect(GetEntityContextId());
|
||||
EntityHighlightMessages::Bus::Handler::BusConnect();
|
||||
EntityOutlinerModelNotificationBus::Handler::BusConnect();
|
||||
@@ -562,7 +569,13 @@ namespace AzToolsFramework
|
||||
|
||||
if (m_selectedEntityIds.size() == 1)
|
||||
{
|
||||
contextMenu->addAction(m_actionToRenameSelection);
|
||||
auto entityId = m_selectedEntityIds.front();
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
|
||||
|
||||
if (!entityUiHandler || entityUiHandler->CanRename(entityId))
|
||||
{
|
||||
contextMenu->addAction(m_actionToRenameSelection);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_selectedEntityIds.size() == 1)
|
||||
@@ -688,11 +701,17 @@ namespace AzToolsFramework
|
||||
|
||||
if (m_selectedEntityIds.size() == 1)
|
||||
{
|
||||
const QModelIndex proxyIndex = GetIndexFromEntityId(m_selectedEntityIds.front());
|
||||
if (proxyIndex.isValid())
|
||||
auto entityId = m_selectedEntityIds.front();
|
||||
auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId);
|
||||
|
||||
if (!entityUiHandler || entityUiHandler->CanRename(entityId))
|
||||
{
|
||||
m_gui->m_objectTree->setCurrentIndex(proxyIndex);
|
||||
m_gui->m_objectTree->QTreeView::edit(proxyIndex);
|
||||
const QModelIndex proxyIndex = GetIndexFromEntityId(entityId);
|
||||
if (proxyIndex.isValid())
|
||||
{
|
||||
m_gui->m_objectTree->setCurrentIndex(proxyIndex);
|
||||
m_gui->m_objectTree->QTreeView::edit(proxyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Ui
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class EditorEntityUiInterface;
|
||||
class EntityOutlinerListModel;
|
||||
class EntityOutlinerSortFilterProxyModel;
|
||||
|
||||
@@ -193,6 +194,8 @@ namespace AzToolsFramework
|
||||
EntityIdSet m_entitiesToSort;
|
||||
EntityOutliner::DisplaySortMode m_sortMode;
|
||||
bool m_sortContentQueued;
|
||||
|
||||
EditorEntityUiInterface* m_editorEntityUiInterface = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -50,11 +50,31 @@ namespace AzToolsFramework
|
||||
return QPixmap(m_levelRootIconPath);
|
||||
}
|
||||
|
||||
QString LevelRootUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const
|
||||
{
|
||||
QString infoString;
|
||||
|
||||
AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId);
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
infoString =
|
||||
QObject::tr("<span style=\"font-style: italic; font-weight: 400;\">(%1)</span>").arg(path.Filename().Native().data());
|
||||
}
|
||||
|
||||
return infoString;
|
||||
}
|
||||
|
||||
bool LevelRootUiHandler::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LevelRootUiHandler::CanRename(AZ::EntityId /*entityId*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void LevelRootUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
|
||||
{
|
||||
if (!painter)
|
||||
|
||||
@@ -34,7 +34,9 @@ namespace AzToolsFramework
|
||||
|
||||
// EditorEntityUiHandler...
|
||||
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
|
||||
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
|
||||
bool CanToggleLockVisibility(AZ::EntityId entityId) const override;
|
||||
bool CanRename(AZ::EntityId entityId) const override;
|
||||
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
private:
|
||||
|
||||
+47
-10
@@ -310,6 +310,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
initEntityPropertyEditorResources();
|
||||
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
AZ_Assert(m_prefabPublicInterface != nullptr, "EntityPropertyEditor requires a PrefabPublicInterface instance on Initialize.");
|
||||
|
||||
setObjectName("EntityPropertyEditor");
|
||||
setAcceptDrops(true);
|
||||
|
||||
@@ -405,8 +408,6 @@ namespace AzToolsFramework
|
||||
CreateActions();
|
||||
UpdateContents();
|
||||
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
|
||||
EditorEntityContextNotificationBus::Handler::BusConnect();
|
||||
|
||||
//forced to register global event filter with application for selection
|
||||
@@ -693,11 +694,38 @@ namespace AzToolsFramework
|
||||
m_gui->m_entityIcon->repaint();
|
||||
}
|
||||
|
||||
EntityPropertyEditor::InspectorLayout EntityPropertyEditor::GetCurrentInspectorLayout() const
|
||||
{
|
||||
if (!m_prefabsAreEnabled)
|
||||
{
|
||||
return m_isLevelEntityEditor ? InspectorLayout::LEVEL : InspectorLayout::ENTITY;
|
||||
}
|
||||
|
||||
AZ::EntityId levelContainerEntityId = m_prefabPublicInterface->GetLevelInstanceContainerEntityId();
|
||||
if (AZStd::find(m_selectedEntityIds.begin(), m_selectedEntityIds.end(), levelContainerEntityId) != m_selectedEntityIds.end())
|
||||
{
|
||||
if (m_selectedEntityIds.size() > 1)
|
||||
{
|
||||
return InspectorLayout::INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return InspectorLayout::LEVEL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return InspectorLayout::ENTITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::UpdateEntityDisplay()
|
||||
{
|
||||
UpdateStatusComboBox();
|
||||
|
||||
if (m_isLevelEntityEditor)
|
||||
InspectorLayout layout = GetCurrentInspectorLayout();
|
||||
|
||||
if (layout == InspectorLayout::LEVEL)
|
||||
{
|
||||
AZStd::string levelName;
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(levelName, &AzToolsFramework::EditorRequests::GetLevelName);
|
||||
@@ -737,13 +765,20 @@ namespace AzToolsFramework
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
SelectionEntityTypeInfo result = SelectionEntityTypeInfo::None;
|
||||
|
||||
if (m_isLevelEntityEditor)
|
||||
InspectorLayout layout = GetCurrentInspectorLayout();
|
||||
|
||||
if (layout == InspectorLayout::LEVEL)
|
||||
{
|
||||
// The Level Inspector should only have a list of selectable components after the
|
||||
// level entity itself is valid (i.e. "selected").
|
||||
return selection.empty() ? SelectionEntityTypeInfo::None : SelectionEntityTypeInfo::LevelEntity;
|
||||
}
|
||||
|
||||
if (layout == InspectorLayout::INVALID)
|
||||
{
|
||||
return SelectionEntityTypeInfo::Mixed;
|
||||
}
|
||||
|
||||
for (AZ::EntityId selectedEntityId : selection)
|
||||
{
|
||||
bool isLayerEntity = false;
|
||||
@@ -909,16 +944,18 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool isLevelLayout = GetCurrentInspectorLayout() == InspectorLayout::LEVEL;
|
||||
|
||||
m_gui->m_entityDetailsLabel->setText(entityDetailsLabelText);
|
||||
m_gui->m_entityDetailsLabel->setVisible(entityDetailsVisible);
|
||||
m_gui->m_entityNameEditor->setVisible(hasEntitiesDisplayed);
|
||||
m_gui->m_entityNameLabel->setVisible(hasEntitiesDisplayed);
|
||||
m_gui->m_entityIcon->setVisible(hasEntitiesDisplayed);
|
||||
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_pinButton->setVisible(m_overrideSelectedEntityIds.empty() && hasEntitiesDisplayed && !m_isSystemEntityEditor);
|
||||
m_gui->m_statusLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
|
||||
m_gui->m_statusComboBox->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
|
||||
m_gui->m_entityIdLabel->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
|
||||
m_gui->m_entityIdText->setVisible(hasEntitiesDisplayed && !m_isSystemEntityEditor && !isLevelLayout);
|
||||
|
||||
bool displayComponentSearchBox = hasEntitiesDisplayed;
|
||||
if (hasEntitiesDisplayed)
|
||||
@@ -941,7 +978,7 @@ namespace AzToolsFramework
|
||||
UpdateEntityDisplay();
|
||||
}
|
||||
|
||||
m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_darkBox->setVisible(displayComponentSearchBox && !m_isSystemEntityEditor && !isLevelLayout);
|
||||
m_gui->m_entitySearchBox->setVisible(displayComponentSearchBox);
|
||||
|
||||
bool displayAddComponentMenu = CanAddComponentsToSelection(selectionEntityTypeInfo);
|
||||
|
||||
+9
@@ -521,6 +521,15 @@ namespace AzToolsFramework
|
||||
bool m_isSystemEntityEditor;
|
||||
bool m_isLevelEntityEditor = false;
|
||||
|
||||
enum class InspectorLayout
|
||||
{
|
||||
ENTITY = 0, // All selected entities are regular entities
|
||||
LEVEL, // The selected entity is the level prefab container entity
|
||||
INVALID // Other entities are selected alongside the level prefab container entity
|
||||
};
|
||||
|
||||
InspectorLayout GetCurrentInspectorLayout() const;
|
||||
|
||||
// the spacer's job is to make sure that its always at the end of the list of components.
|
||||
QSpacerItem* m_spacer;
|
||||
bool m_isAlreadyQueuedRefresh;
|
||||
|
||||
@@ -28,8 +28,9 @@ ly_add_target(
|
||||
${pal_dir}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::OpenSSL
|
||||
AZ::AzCore
|
||||
PUBLIC
|
||||
3rdParty::OpenSSL
|
||||
)
|
||||
|
||||
ly_add_source_properties(
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "2DViewport.h"
|
||||
#include "CryEditDoc.h"
|
||||
#include "DisplaySettings.h"
|
||||
#include "EditTool.h"
|
||||
#include "GameEngine.h"
|
||||
#include "Settings.h"
|
||||
#include "ViewManager.h"
|
||||
@@ -1117,11 +1116,6 @@ void Q2DViewport::DrawObjects(DisplayContext& dc)
|
||||
GetIEditor()->GetObjectManager()->Display(dc);
|
||||
}
|
||||
|
||||
// Display editing tool.
|
||||
if (GetEditTool())
|
||||
{
|
||||
GetEditTool()->Display(dc);
|
||||
}
|
||||
dc.PopMatrix();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,142 +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 "AlignTool.h"
|
||||
|
||||
// Editor
|
||||
#include "Objects/BaseObject.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAlignPickCallback::m_bActive = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Called when object picked.
|
||||
void CAlignPickCallback::OnPick(CBaseObject* picked)
|
||||
{
|
||||
Matrix34 pickedTM(picked->GetWorldTM());
|
||||
|
||||
AABB pickedAABB;
|
||||
picked->GetBoundBox(pickedAABB);
|
||||
pickedAABB.Move(-pickedTM.GetTranslation());
|
||||
Vec3 pickedPivot = pickedAABB.GetCenter();
|
||||
|
||||
AABB pickedLocalAABB;
|
||||
picked->GetLocalBounds(pickedLocalAABB);
|
||||
|
||||
const Quat& pickedRot = picked->GetRotation();
|
||||
const Vec3& pickedScale = picked->GetScale();
|
||||
const Vec3& pickedPos = picked->GetPos();
|
||||
|
||||
bool bKeepScale = CheckVirtualKey(Qt::Key_Shift);
|
||||
bool bKeepRotation = CheckVirtualKey(Qt::Key_Alt);
|
||||
bool bAlignToBoundBox = CheckVirtualKey(Qt::Key_Control);
|
||||
bool bApplyTransform = !bKeepScale && !bKeepRotation && !bAlignToBoundBox;
|
||||
|
||||
{
|
||||
bool bUndo = !CUndo::IsRecording();
|
||||
if (bUndo)
|
||||
{
|
||||
GetIEditor()->BeginUndo();
|
||||
}
|
||||
|
||||
CSelectionGroup* selGroup = GetIEditor()->GetSelection();
|
||||
selGroup->FilterParents();
|
||||
|
||||
for (int i = 0; i < selGroup->GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* pMovedObj = selGroup->GetFilteredObject(i);
|
||||
|
||||
if (bKeepScale || bKeepRotation || bApplyTransform)
|
||||
{
|
||||
if (bKeepScale && bKeepRotation) // Keep scale and rotation of a moved object
|
||||
{
|
||||
pMovedObj->SetWorldTM(Matrix34::Create(pMovedObj->GetScale(), pMovedObj->GetRotation(), pickedPos), eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
else if (bKeepScale) // Keep only scale of a moved object
|
||||
{
|
||||
pMovedObj->SetWorldTM(Matrix34::Create(pMovedObj->GetScale(), pickedRot, pickedPos), eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
else if (bKeepRotation) // Keep only rotation of a moved object
|
||||
{
|
||||
pMovedObj->SetWorldTM(Matrix34::Create(pickedScale, pMovedObj->GetRotation(), pickedPos), eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
else // Scale, Rotation and Position of a picked object are applied to a moved object.
|
||||
{
|
||||
pMovedObj->SetWorldTM(pickedTM, eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
}
|
||||
else if (bAlignToBoundBox) // align to the bounding box.
|
||||
{
|
||||
if (pickedLocalAABB.GetVolume() == 0.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AABB movedLocalAABB;
|
||||
pMovedObj->GetLocalBounds(movedLocalAABB);
|
||||
if (fabs(movedLocalAABB.max.x - movedLocalAABB.min.x) < VEC_EPSILON &&
|
||||
fabs(movedLocalAABB.max.y - movedLocalAABB.min.y) < VEC_EPSILON &&
|
||||
fabs(movedLocalAABB.max.z - movedLocalAABB.min.z) < VEC_EPSILON)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vec3& movedScale(pMovedObj->GetScale());
|
||||
Matrix34 movedScaleTM = Matrix34::CreateScale(movedScale);
|
||||
AABB movedLocalScaledAABB;
|
||||
movedLocalScaledAABB.min = movedScaleTM.TransformVector(movedLocalAABB.min);
|
||||
movedLocalScaledAABB.max = movedScaleTM.TransformVector(movedLocalAABB.max);
|
||||
|
||||
float fMovedWidth = movedLocalScaledAABB.max.x - movedLocalScaledAABB.min.x;
|
||||
float fMovedHeight = movedLocalScaledAABB.max.z - movedLocalScaledAABB.min.z;
|
||||
float fMovedLength = movedLocalScaledAABB.max.y - movedLocalScaledAABB.min.y;
|
||||
|
||||
Matrix34 pickedScaleTM = Matrix34::CreateScale(picked->GetScale());
|
||||
AABB pickedLocalScaledAABB;
|
||||
pickedLocalScaledAABB.min = pickedScaleTM.TransformVector(pickedLocalAABB.min);
|
||||
pickedLocalScaledAABB.max = pickedScaleTM.TransformVector(pickedLocalAABB.max);
|
||||
float fScaledPickedtWidth = pickedLocalScaledAABB.max.x - pickedLocalScaledAABB.min.x;
|
||||
float fScaledPickedHeight = pickedLocalScaledAABB.max.z - pickedLocalScaledAABB.min.z;
|
||||
float fScaledPickedLength = pickedLocalScaledAABB.max.y - pickedLocalScaledAABB.min.y;
|
||||
|
||||
Vec3 scale((fScaledPickedtWidth / fMovedWidth) * movedScale.x, (fScaledPickedLength / fMovedLength) * movedScale.y, (fScaledPickedHeight / fMovedHeight) * movedScale.z);
|
||||
Matrix34 scaleRotTM = Matrix34::Create(scale, pickedRot, Vec3(0, 0, 0));
|
||||
Vec3 movedPivot = scaleRotTM.TransformVector(movedLocalAABB.GetCenter());
|
||||
|
||||
pMovedObj->SetWorldTM(Matrix34::Create(scale, pickedRot, Vec3(pickedPos + (pickedPivot - movedPivot))), eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
}
|
||||
m_bActive = false;
|
||||
if (bUndo)
|
||||
{
|
||||
GetIEditor()->AcceptUndo("Align To Object");
|
||||
}
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
//! Called when pick mode cancelled.
|
||||
void CAlignPickCallback::OnCancelPick()
|
||||
{
|
||||
m_bActive = false;
|
||||
delete this;
|
||||
}
|
||||
|
||||
//! Return true if specified object is pickable.
|
||||
bool CAlignPickCallback::OnPickFilter([[maybe_unused]] CBaseObject* filterObject)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
@@ -1,40 +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_ALIGNTOOL_H
|
||||
#define CRYINCLUDE_EDITOR_ALIGNTOOL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CAlignPickCallback
|
||||
: public IPickObjectCallback
|
||||
{
|
||||
public:
|
||||
CAlignPickCallback() { m_bActive = true; };
|
||||
//! Called when object picked.
|
||||
virtual void OnPick(CBaseObject* picked);
|
||||
//! Called when pick mode cancelled.
|
||||
virtual void OnCancelPick();
|
||||
//! Return true if specified object is pickable.
|
||||
virtual bool OnPickFilter(CBaseObject* filterObject);
|
||||
|
||||
static bool IsActive() { return m_bActive; }
|
||||
|
||||
virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return true; }
|
||||
private:
|
||||
static bool m_bActive;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_ALIGNTOOL_H
|
||||
@@ -1,588 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "QRollupCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QMenu>
|
||||
#include <QStylePainter>
|
||||
#include <QVBoxLayout>
|
||||
#include <QSettings>
|
||||
#include <QToolButton>
|
||||
#include <QStyleOptionToolButton>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class QRollupCtrlButton
|
||||
: public QToolButton
|
||||
{
|
||||
public:
|
||||
QRollupCtrlButton(QWidget* parent);
|
||||
|
||||
inline void setSelected(bool b) { selected = b; update(); }
|
||||
inline bool isSelected() const { return selected; }
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
private:
|
||||
bool selected;
|
||||
};
|
||||
|
||||
QRollupCtrlButton::QRollupCtrlButton(QWidget* parent)
|
||||
: QToolButton(parent)
|
||||
, selected(true)
|
||||
{
|
||||
setBackgroundRole(QPalette::Window);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
setStyleSheet("* {margin: 2px 5px 2px 5px; border: 1px solid #CBA457;}");
|
||||
}
|
||||
|
||||
QSize QRollupCtrlButton::sizeHint() const
|
||||
{
|
||||
QSize iconSize(8, 8);
|
||||
if (!icon().isNull())
|
||||
{
|
||||
int icone = style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
iconSize += QSize(icone + 2, icone);
|
||||
}
|
||||
QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text()) + QSize(0, 8);
|
||||
|
||||
QSize total(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height()));
|
||||
return total.expandedTo(QApplication::globalStrut());
|
||||
}
|
||||
|
||||
QSize QRollupCtrlButton::minimumSizeHint() const
|
||||
{
|
||||
if (icon().isNull())
|
||||
{
|
||||
return QSize();
|
||||
}
|
||||
int icone = style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
return QSize(icone + 8, icone + 8);
|
||||
}
|
||||
|
||||
void QRollupCtrlButton::paintEvent(QPaintEvent*)
|
||||
{
|
||||
QStylePainter p(this);
|
||||
// draw the background manually, not to clash with UI 2.0 style shets
|
||||
// the numbers here are taken from the stylesheet in the constructor
|
||||
p.fillRect(QRect(5, 1, width() - 10, height() - 3), QColor(52, 52, 52));
|
||||
|
||||
{
|
||||
QStyleOptionToolButton opt;
|
||||
initStyleOption(&opt);
|
||||
if (isSelected())
|
||||
{
|
||||
if (opt.state & QStyle::State_MouseOver)
|
||||
{
|
||||
opt.state |= QStyle::State_Sunken;
|
||||
}
|
||||
opt.state |= QStyle::State_MouseOver;
|
||||
}
|
||||
p.drawComplexControl(QStyle::CC_ToolButton, opt);
|
||||
}
|
||||
|
||||
{
|
||||
p.setPen(QPen(QColor(132, 128, 125)));
|
||||
|
||||
int top = height() / 2 - 2;
|
||||
p.drawLine(2, top, 4, top);
|
||||
p.drawLine(width() - 5, top, width() - 3, top);
|
||||
|
||||
int bottom = !isSelected() ? top + 4 : height();
|
||||
p.drawLine(2, bottom, 2, top);
|
||||
p.drawLine(width() - 3, bottom, width() - 3, top);
|
||||
|
||||
if (!isSelected())
|
||||
{
|
||||
p.drawLine(2, bottom, 4, bottom);
|
||||
p.drawLine(width() - 5, bottom, width() - 3, bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QRollupCtrl::Page* QRollupCtrl::page(QWidget* widget) const
|
||||
{
|
||||
if (!widget)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
|
||||
{
|
||||
if ((*i).widget == widget)
|
||||
{
|
||||
return (Page*)&(*i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QRollupCtrl::Page* QRollupCtrl::page(int index)
|
||||
{
|
||||
if (index >= 0 && index < m_pageList.size())
|
||||
{
|
||||
return &m_pageList[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QRollupCtrl::Page* QRollupCtrl::page(int index) const
|
||||
{
|
||||
if (index >= 0 && index < m_pageList.size())
|
||||
{
|
||||
return &m_pageList.at(index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void QRollupCtrl::Page::setText(const QString& text) { button->setText(text); }
|
||||
inline void QRollupCtrl::Page::setIcon(const QIcon& is) { button->setIcon(is); }
|
||||
inline void QRollupCtrl::Page::setToolTip(const QString& tip) { button->setToolTip(tip); }
|
||||
inline QString QRollupCtrl::Page::text() const { return button->text(); }
|
||||
inline QIcon QRollupCtrl::Page::icon() const { return button->icon(); }
|
||||
inline QString QRollupCtrl::Page::toolTip() const { return button->toolTip(); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QRollupCtrl::QRollupCtrl(QWidget* parent)
|
||||
: QScrollArea(parent)
|
||||
, m_layout(0)
|
||||
{
|
||||
m_body = new QWidget(this);
|
||||
m_body->setBackgroundRole(QPalette::Button);
|
||||
setWidgetResizable(true);
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
setWidget(m_body);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
relayout();
|
||||
}
|
||||
|
||||
QRollupCtrl::~QRollupCtrl()
|
||||
{
|
||||
foreach(const QRollupCtrl::Page & c, m_pageList)
|
||||
disconnect(c.widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
|
||||
}
|
||||
|
||||
void QRollupCtrl::readSettings(const QString& qSettingsGroup)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(qSettingsGroup);
|
||||
|
||||
int i = 0;
|
||||
foreach(const QRollupCtrl::Page & c, m_pageList) {
|
||||
QString qObjectName = c.widget->objectName();
|
||||
|
||||
bool bHidden = settings.value(qObjectName, true).toBool();
|
||||
setIndexVisible(i++, !bHidden);
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void QRollupCtrl::writeSettings(const QString& qSettingsGroup)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup(qSettingsGroup);
|
||||
|
||||
for (int i = 0; i < count(); i++)
|
||||
{
|
||||
QString qObjectName;
|
||||
bool bHidden = isPageHidden(i, qObjectName);
|
||||
|
||||
settings.setValue(qObjectName, bHidden);
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::updateTabs()
|
||||
{
|
||||
for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
|
||||
{
|
||||
QRollupCtrlButton* tB = (*i).button;
|
||||
QWidget* tW = (*i).sv;
|
||||
tB->setSelected(tW->isVisible());
|
||||
tB->update();
|
||||
}
|
||||
}
|
||||
|
||||
int QRollupCtrl::insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text)
|
||||
{
|
||||
if (!widget)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; });
|
||||
if (it != m_pageList.cend())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
connect(widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
|
||||
|
||||
QRollupCtrl::Page c;
|
||||
c.widget = widget;
|
||||
c.button = new QRollupCtrlButton(m_body);
|
||||
c.button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(c.button, &QRollupCtrlButton::clicked, this, &QRollupCtrl::_q_buttonClicked);
|
||||
connect(c.button, &QRollupCtrlButton::customContextMenuRequested, this, &QRollupCtrl::_q_custumButtonMenu);
|
||||
|
||||
c.sv = new QFrame(m_body);
|
||||
c.sv->setObjectName("rollupPaneFrame");
|
||||
// c.sv->setFixedHeight(qMax(widget->sizeHint().height(), widget->size().height()));
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
layout->setMargin(3);
|
||||
layout->addWidget(widget);
|
||||
c.sv->setLayout(layout);
|
||||
c.sv->setStyleSheet("QFrame#rollupPaneFrame {margin: 0px 2px 2px 2px; border: 1px solid #84807D; border-top:0px;}");
|
||||
c.sv->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
c.sv->show();
|
||||
|
||||
c.setText(text);
|
||||
c.setIcon(icon);
|
||||
|
||||
const int numPages = m_pageList.count();
|
||||
if (index < 0 || index >= numPages)
|
||||
{
|
||||
m_pageList.append(c);
|
||||
index = numPages - 1;
|
||||
m_layout->insertWidget(m_layout->count() - 1, c.button);
|
||||
m_layout->insertWidget(m_layout->count() - 1, c.sv);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pageList.insert(index, c);
|
||||
relayout();
|
||||
}
|
||||
|
||||
c.button->show();
|
||||
|
||||
updateTabs();
|
||||
itemInserted(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
void QRollupCtrl::_q_buttonClicked()
|
||||
{
|
||||
QObject* tb = sender();
|
||||
QWidget* item = 0;
|
||||
for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
|
||||
{
|
||||
if ((*i).button == tb)
|
||||
{
|
||||
item = (*i).widget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
setIndexVisible(indexOf(item), !item->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
int QRollupCtrl::count() const
|
||||
{
|
||||
return m_pageList.count();
|
||||
}
|
||||
|
||||
bool QRollupCtrl::isPageHidden(int index, QString& qObjectName) const
|
||||
{
|
||||
if (index < 0 || index >= m_pageList.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const QRollupCtrl::Page& c = m_pageList.at(index);
|
||||
qObjectName = c.widget->objectName();
|
||||
return c.sv->isHidden();
|
||||
}
|
||||
|
||||
void QRollupCtrl::setIndexVisible(int index, bool visible)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(index);
|
||||
if (!c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->sv->isHidden() && visible)
|
||||
{
|
||||
c->sv->show();
|
||||
}
|
||||
else if (c->sv->isVisible() && !visible)
|
||||
{
|
||||
c->sv->hide();
|
||||
}
|
||||
updateTabs();
|
||||
}
|
||||
|
||||
void QRollupCtrl::setWidgetVisible(QWidget* widget, bool visible)
|
||||
{
|
||||
setIndexVisible(indexOf(widget), visible);
|
||||
}
|
||||
|
||||
void QRollupCtrl::relayout()
|
||||
{
|
||||
delete m_layout;
|
||||
m_layout = new QVBoxLayout(m_body);
|
||||
m_layout->setMargin(3);
|
||||
m_layout->setSpacing(0);
|
||||
for (QRollupCtrl::PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
|
||||
{
|
||||
m_layout->addWidget((*i).button);
|
||||
m_layout->addWidget((*i).sv);
|
||||
}
|
||||
m_layout->addStretch();
|
||||
updateTabs();
|
||||
}
|
||||
|
||||
void QRollupCtrl::_q_widgetDestroyed(QObject* object)
|
||||
{
|
||||
// no verification - vtbl corrupted already
|
||||
QWidget* p = (QWidget*)object;
|
||||
|
||||
QRollupCtrl::Page* c = page(p);
|
||||
if (!p || !c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_layout->removeWidget(c->sv);
|
||||
m_layout->removeWidget(c->button);
|
||||
c->sv->deleteLater(); // page might still be a child of sv
|
||||
delete c->button;
|
||||
|
||||
m_pageList.removeOne(*c);
|
||||
}
|
||||
|
||||
void QRollupCtrl::_q_custumButtonMenu([[maybe_unused]] const QPoint& pos)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction("Expand All")->setData(-1);
|
||||
menu.addAction("Collapse All")->setData(-2);
|
||||
menu.addSeparator();
|
||||
for (int i = 0; i < m_pageList.size(); ++i)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(i);
|
||||
QAction* action = menu.addAction(c->button->text());
|
||||
action->setCheckable(true);
|
||||
action->setChecked(c->sv->isVisible());
|
||||
action->setData(i);
|
||||
}
|
||||
|
||||
QAction* action = menu.exec(QCursor::pos());
|
||||
if (!action)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int res = action->data().toInt();
|
||||
switch (res)
|
||||
{
|
||||
case -1: // fall through
|
||||
case -2:
|
||||
expandAllPages(res == -1);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
QRollupCtrl::Page* c = page(res);
|
||||
if (c)
|
||||
{
|
||||
setIndexVisible(res, !c->sv->isVisible());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::expandAllPages(bool v)
|
||||
{
|
||||
for (int i = 0; i < m_pageList.size(); i++)
|
||||
{
|
||||
setIndexVisible(i, v);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void QRollupCtrl::clear()
|
||||
{
|
||||
while (!m_pageList.isEmpty())
|
||||
{
|
||||
removeItem(0);
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::removeItem(QWidget* widget)
|
||||
{
|
||||
auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; });
|
||||
if (it != m_pageList.cend())
|
||||
{
|
||||
removeItem(it - m_pageList.cbegin());
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::removeItem(int index)
|
||||
{
|
||||
if (QWidget* w = widget(index))
|
||||
{
|
||||
disconnect(w, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
|
||||
w->setParent(this);
|
||||
// destroy internal data
|
||||
_q_widgetDestroyed(w);
|
||||
itemRemoved(index);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* QRollupCtrl::widget(int index) const
|
||||
{
|
||||
if (index < 0 || index >= (int) m_pageList.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_pageList.at(index).widget;
|
||||
}
|
||||
|
||||
int QRollupCtrl::indexOf(QWidget* widget) const
|
||||
{
|
||||
QRollupCtrl::Page* c = page(widget);
|
||||
return c ? m_pageList.indexOf(*c) : -1;
|
||||
}
|
||||
|
||||
void QRollupCtrl::setItemEnabled(int index, bool enabled)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(index);
|
||||
if (!c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
c->button->setEnabled(enabled);
|
||||
if (!enabled)
|
||||
{
|
||||
int curIndexUp = index;
|
||||
int curIndexDown = curIndexUp;
|
||||
const int count = m_pageList.count();
|
||||
while (curIndexUp > 0 || curIndexDown < count - 1)
|
||||
{
|
||||
if (curIndexDown < count - 1)
|
||||
{
|
||||
if (page(++curIndexDown)->button->isEnabled())
|
||||
{
|
||||
index = curIndexDown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curIndexUp > 0)
|
||||
{
|
||||
if (page(--curIndexUp)->button->isEnabled())
|
||||
{
|
||||
index = curIndexUp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::setItemText(int index, const QString& text)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(index);
|
||||
if (c)
|
||||
{
|
||||
c->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::setItemIcon(int index, const QIcon& icon)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(index);
|
||||
if (c)
|
||||
{
|
||||
c->setIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
void QRollupCtrl::setItemToolTip(int index, const QString& toolTip)
|
||||
{
|
||||
QRollupCtrl::Page* c = page(index);
|
||||
if (c)
|
||||
{
|
||||
c->setToolTip(toolTip);
|
||||
}
|
||||
}
|
||||
|
||||
bool QRollupCtrl::isItemEnabled(int index) const
|
||||
{
|
||||
const QRollupCtrl::Page* c = page(index);
|
||||
return c && c->button->isEnabled();
|
||||
}
|
||||
|
||||
QString QRollupCtrl::itemText(int index) const
|
||||
{
|
||||
const QRollupCtrl::Page* c = page(index);
|
||||
return (c ? c->text() : QString());
|
||||
}
|
||||
|
||||
QIcon QRollupCtrl::itemIcon(int index) const
|
||||
{
|
||||
const QRollupCtrl::Page* c = page(index);
|
||||
return (c ? c->icon() : QIcon());
|
||||
}
|
||||
|
||||
QString QRollupCtrl::itemToolTip(int index) const
|
||||
{
|
||||
const QRollupCtrl::Page* c = page(index);
|
||||
return (c ? c->toolTip() : QString());
|
||||
}
|
||||
|
||||
void QRollupCtrl::changeEvent(QEvent* ev)
|
||||
{
|
||||
if (ev->type() == QEvent::StyleChange)
|
||||
{
|
||||
updateTabs();
|
||||
}
|
||||
QFrame::changeEvent(ev);
|
||||
}
|
||||
|
||||
void QRollupCtrl::showEvent(QShowEvent* ev)
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
updateTabs();
|
||||
}
|
||||
IEditor* pEditor = GetIEditor();
|
||||
pEditor->SetEditMode(EEditMode::eEditModeSelect);
|
||||
QFrame::showEvent(ev);
|
||||
}
|
||||
|
||||
void QRollupCtrl::itemInserted(int index)
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
void QRollupCtrl::itemRemoved(int index)
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
|
||||
#include <Controls/moc_QRollupCtrl.cpp>
|
||||
@@ -1,126 +0,0 @@
|
||||
#ifndef CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QFrame>
|
||||
#include <QScrollArea>
|
||||
#include <QIcon>
|
||||
#endif
|
||||
|
||||
class QVBoxLayout;
|
||||
class QRollupCtrlButton;
|
||||
|
||||
class QRollupCtrl
|
||||
: public QScrollArea
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count)
|
||||
|
||||
public:
|
||||
explicit QRollupCtrl(QWidget* parent = 0);
|
||||
~QRollupCtrl();
|
||||
|
||||
int addItem(QWidget* widget, const QString& text);
|
||||
int addItem(QWidget* widget, const QIcon& icon, const QString& text);
|
||||
int insertItem(int index, QWidget* widget, const QString& text);
|
||||
int insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text);
|
||||
|
||||
void clear();
|
||||
void removeItem(QWidget* widget);
|
||||
void removeItem(int index);
|
||||
|
||||
void setItemEnabled(int index, bool enabled);
|
||||
bool isItemEnabled(int index) const;
|
||||
|
||||
void setItemText(int index, const QString& text);
|
||||
QString itemText(int index) const;
|
||||
|
||||
void setItemIcon(int index, const QIcon& icon);
|
||||
QIcon itemIcon(int index) const;
|
||||
|
||||
void setItemToolTip(int index, const QString& toolTip);
|
||||
QString itemToolTip(int index) const;
|
||||
|
||||
QWidget* widget(int index) const;
|
||||
int indexOf(QWidget* widget) const;
|
||||
int count() const;
|
||||
|
||||
void readSettings (const QString& qSettingsGroup);
|
||||
void writeSettings(const QString& qSettingsGroup);
|
||||
|
||||
public slots:
|
||||
void setIndexVisible(int index, bool visible);
|
||||
void setWidgetVisible(QWidget* widget, bool visible);
|
||||
void expandAllPages(bool v);
|
||||
|
||||
protected:
|
||||
virtual void itemInserted(int index);
|
||||
virtual void itemRemoved(int index);
|
||||
void changeEvent(QEvent*) override;
|
||||
void showEvent(QShowEvent*) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QRollupCtrl)
|
||||
|
||||
struct Page
|
||||
{
|
||||
QRollupCtrlButton* button;
|
||||
QFrame* sv;
|
||||
QWidget* widget;
|
||||
|
||||
void setText(const QString& text);
|
||||
void setIcon(const QIcon& is);
|
||||
void setToolTip(const QString& tip);
|
||||
QString text() const;
|
||||
QIcon icon() const;
|
||||
QString toolTip() const;
|
||||
|
||||
inline bool operator==(const Page& other) const
|
||||
{
|
||||
return widget == other.widget;
|
||||
}
|
||||
};
|
||||
typedef QList<Page> PageList;
|
||||
|
||||
Page* page(QWidget* widget) const;
|
||||
const Page* page(int index) const;
|
||||
Page* page(int index);
|
||||
|
||||
void updateTabs();
|
||||
void relayout();
|
||||
bool isPageHidden(int index, QString& qObjectName) const;
|
||||
|
||||
QWidget* m_body;
|
||||
PageList m_pageList;
|
||||
QVBoxLayout* m_layout;
|
||||
|
||||
private slots:
|
||||
void _q_buttonClicked();
|
||||
void _q_widgetDestroyed(QObject*);
|
||||
void _q_custumButtonMenu(const QPoint&);
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline int QRollupCtrl::addItem(QWidget* item, const QString& text)
|
||||
{ return insertItem(-1, item, QIcon(), text); }
|
||||
inline int QRollupCtrl::addItem(QWidget* item, const QIcon& iconSet, const QString& text)
|
||||
{ return insertItem(-1, item, iconSet, text); }
|
||||
inline int QRollupCtrl::insertItem(int index, QWidget* item, const QString& text)
|
||||
{ return insertItem(index, item, QIcon(), text); }
|
||||
|
||||
#endif
|
||||
@@ -1,171 +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.
|
||||
|
||||
// Description : implementation file
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
// Editor
|
||||
#include "CryEditDoc.h"
|
||||
#include "EditTool.h"
|
||||
#include "ToolButton.h"
|
||||
|
||||
|
||||
QEditorToolButton::QEditorToolButton(QWidget* parent /* = nullptr */)
|
||||
: QPushButton(parent)
|
||||
, m_styleSheet(styleSheet())
|
||||
, m_toolClass(nullptr)
|
||||
, m_toolCreated(nullptr)
|
||||
, m_needDocument(true)
|
||||
{
|
||||
setSizePolicy({ QSizePolicy::Expanding, QSizePolicy::Fixed });
|
||||
connect(this, &QAbstractButton::clicked, this, &QEditorToolButton::OnClicked);
|
||||
GetIEditor()->RegisterNotifyListener(this);
|
||||
}
|
||||
|
||||
QEditorToolButton::~QEditorToolButton()
|
||||
{
|
||||
GetIEditor()->UnregisterNotifyListener(this);
|
||||
}
|
||||
|
||||
void QEditorToolButton::SetToolName(const QString& editToolName, const QString& userDataKey, void* userData)
|
||||
{
|
||||
IClassDesc* klass = GetIEditor()->GetClassFactory()->FindClass(editToolName.toUtf8().data());
|
||||
if (!klass)
|
||||
{
|
||||
Warning(QStringLiteral("Editor Tool %1 not registered.").arg(editToolName).toUtf8().data());
|
||||
return;
|
||||
}
|
||||
if (klass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL)
|
||||
{
|
||||
Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data());
|
||||
return;
|
||||
}
|
||||
|
||||
QScopedPointer<QObject> o(klass->CreateQObject());
|
||||
if (!qobject_cast<CEditTool*>(o.data()))
|
||||
{
|
||||
Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data());
|
||||
return;
|
||||
}
|
||||
SetToolClass(o->metaObject(), userDataKey, userData);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void QEditorToolButton::SetToolClass(const QMetaObject* toolClass, const QString& userDataKey, void* userData)
|
||||
{
|
||||
m_toolClass = toolClass;
|
||||
|
||||
m_userData = userData;
|
||||
if (!userDataKey.isEmpty())
|
||||
{
|
||||
m_userDataKey = userDataKey;
|
||||
}
|
||||
}
|
||||
|
||||
void QEditorToolButton::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case eNotify_OnBeginNewScene:
|
||||
case eNotify_OnBeginLoad:
|
||||
case eNotify_OnBeginSceneOpen:
|
||||
{
|
||||
if (m_needDocument)
|
||||
{
|
||||
setEnabled(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eNotify_OnEndNewScene:
|
||||
case eNotify_OnEndLoad:
|
||||
case eNotify_OnEndSceneOpen:
|
||||
{
|
||||
if (m_needDocument)
|
||||
{
|
||||
setEnabled(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eNotify_OnEditToolChange:
|
||||
{
|
||||
CEditTool* tool = GetIEditor()->GetEditTool();
|
||||
|
||||
if (!tool || tool != m_toolCreated || tool->metaObject() != m_toolClass)
|
||||
{
|
||||
m_toolCreated = nullptr;
|
||||
SetSelected(false);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QEditorToolButton::OnClicked()
|
||||
{
|
||||
if (!m_toolClass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_needDocument && !GetIEditor()->GetDocument()->IsDocumentReady())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CEditTool* tool = GetIEditor()->GetEditTool();
|
||||
if (tool && tool->IsMoveToObjectModeAfterEnd() && tool->metaObject() == m_toolClass && tool == m_toolCreated)
|
||||
{
|
||||
GetIEditor()->SetEditTool(nullptr);
|
||||
SetSelected(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CEditTool* newTool = qobject_cast<CEditTool*>(m_toolClass->newInstance());
|
||||
if (!newTool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_toolCreated = newTool;
|
||||
|
||||
SetSelected(true);
|
||||
|
||||
if (m_userData)
|
||||
{
|
||||
newTool->SetUserData(m_userDataKey.toUtf8().data(), (void*)m_userData);
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
// Must be last function, can delete this.
|
||||
GetIEditor()->SetEditTool(newTool);
|
||||
}
|
||||
}
|
||||
|
||||
void QEditorToolButton::SetSelected(bool selected)
|
||||
{
|
||||
if (selected)
|
||||
{
|
||||
setStyleSheet(QStringLiteral("QPushButton { background-color: palette(highlight); color: palette(highlighted-text); }"));
|
||||
}
|
||||
else
|
||||
{
|
||||
setStyleSheet(m_styleSheet);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Controls/moc_ToolButton.cpp>
|
||||
@@ -1,60 +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_CONTROLS_TOOLBUTTON_H
|
||||
#define CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H
|
||||
#pragma once
|
||||
|
||||
// ToolButton.h : header file
|
||||
//
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <QPushButton>
|
||||
#endif
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class SANDBOX_API QEditorToolButton
|
||||
: public QPushButton
|
||||
, public IEditorNotifyListener
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
Q_OBJECT
|
||||
// Construction
|
||||
public:
|
||||
QEditorToolButton(QWidget* parent = nullptr);
|
||||
virtual ~QEditorToolButton();
|
||||
|
||||
void SetToolClass(const QMetaObject* toolClass, const QString& userDataKey = 0, void* userData = nullptr);
|
||||
void SetToolName(const QString& editToolName, const QString& userDataKey = 0, void* userData = nullptr);
|
||||
// Set if this tool button relies on a loaded level / ready document. By default every tool button only works if a level is loaded.
|
||||
// However some tools are also used without a loaded level (e.g. UI Emulator)
|
||||
void SetNeedDocument(bool needDocument) { m_needDocument = needDocument; }
|
||||
|
||||
void SetSelected(bool selected);
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
protected:
|
||||
void OnClicked();
|
||||
|
||||
const QString m_styleSheet;
|
||||
|
||||
//! Tool associated with this button.
|
||||
const QMetaObject* m_toolClass;
|
||||
CEditTool* m_toolCreated;
|
||||
QString m_userDataKey;
|
||||
void* m_userData;
|
||||
bool m_needDocument;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H
|
||||
@@ -580,8 +580,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
|
||||
|
||||
auto alignMenu = modifyMenu.AddMenu(tr("Align"));
|
||||
alignMenu.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID);
|
||||
alignMenu.AddAction(ID_OBJECTMODIFY_ALIGN);
|
||||
alignMenu.AddAction(ID_MODIFY_ALIGNOBJTOSURF);
|
||||
|
||||
auto constrainMenu = modifyMenu.AddMenu(tr("Constrain"));
|
||||
constrainMenu.AddAction(ID_SELECT_AXIS_X);
|
||||
|
||||
@@ -95,9 +95,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
#include "Core/QtEditorApplication.h"
|
||||
#include "StringDlg.h"
|
||||
#include "LinkTool.h"
|
||||
#include "AlignTool.h"
|
||||
#include "VoxelAligningTool.h"
|
||||
#include "NewLevelDialog.h"
|
||||
#include "GridSettingsDialog.h"
|
||||
#include "LayoutConfigDialog.h"
|
||||
@@ -112,7 +109,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "DisplaySettings.h"
|
||||
#include "GameEngine.h"
|
||||
|
||||
#include "ObjectCloneTool.h"
|
||||
#include "StartupTraceHandler.h"
|
||||
#include "ThumbnailGenerator.h"
|
||||
#include "ToolsConfigPage.h"
|
||||
@@ -126,7 +122,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "EditorPreferencesDialog.h"
|
||||
#include "GraphicsSettingsDialog.h"
|
||||
#include "FeedbackDialog/FeedbackDialog.h"
|
||||
#include "MatEditMainDlg.h"
|
||||
#include "AnimationContext.h"
|
||||
|
||||
#include "GotoPositionDlg.h"
|
||||
@@ -156,7 +151,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "LevelIndependentFileMan.h"
|
||||
#include "WelcomeScreen/WelcomeScreenDialog.h"
|
||||
#include "Dialogs/DuplicatedObjectsHandlerDlg.h"
|
||||
#include "EditMode/VertexSnappingModeTool.h"
|
||||
|
||||
#include "Controls/ReflectedPropertyControl/PropertyCtrl.h"
|
||||
#include "Controls/ReflectedPropertyControl/ReflectedVar.h"
|
||||
@@ -401,14 +395,9 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
ON_COMMAND(ID_EDITMODE_MOVE, OnEditmodeMove)
|
||||
ON_COMMAND(ID_EDITMODE_ROTATE, OnEditmodeRotate)
|
||||
ON_COMMAND(ID_EDITMODE_SCALE, OnEditmodeScale)
|
||||
ON_COMMAND(ID_EDITTOOL_LINK, OnEditToolLink)
|
||||
ON_COMMAND(ID_EDITTOOL_UNLINK, OnEditToolUnlink)
|
||||
ON_COMMAND(ID_EDITMODE_SELECT, OnEditmodeSelect)
|
||||
ON_COMMAND(ID_EDIT_ESCAPE, OnEditEscape)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_SETAREA, OnObjectSetArea)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_SETHEIGHT, OnObjectSetHeight)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_VERTEXSNAPPING, OnObjectVertexSnapping)
|
||||
ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_FREEZE, OnObjectmodifyFreeze)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_UNFREEZE, OnObjectmodifyUnfreeze)
|
||||
ON_COMMAND(ID_EDITMODE_SELECTAREA, OnEditmodeSelectarea)
|
||||
@@ -418,12 +407,9 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
ON_COMMAND(ID_SELECT_AXIS_XY, OnSelectAxisXy)
|
||||
ON_COMMAND(ID_UNDO, OnUndo)
|
||||
ON_COMMAND(ID_TOOLBAR_WIDGET_REDO, OnUndo) // Can't use the same ID, because for the menu we can't have a QWidgetAction, while for the toolbar we want one
|
||||
ON_COMMAND(ID_EDIT_CLONE, OnEditClone)
|
||||
ON_COMMAND(ID_SELECTION_SAVE, OnSelectionSave)
|
||||
ON_COMMAND(ID_IMPORT_ASSET, OnOpenAssetImporter)
|
||||
ON_COMMAND(ID_SELECTION_LOAD, OnSelectionLoad)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_ALIGN, OnAlignObject)
|
||||
ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel)
|
||||
ON_COMMAND(ID_OBJECTMODIFY_ALIGNTOGRID, OnAlignToGrid)
|
||||
ON_COMMAND(ID_LOCK_SELECTION, OnLockSelection)
|
||||
ON_COMMAND(ID_EDIT_LEVELDATA, OnEditLevelData)
|
||||
@@ -530,12 +516,10 @@ void CCryEditApp::RegisterActionHandlers()
|
||||
|
||||
ON_COMMAND(ID_OPEN_MATERIAL_EDITOR, OnOpenMaterialEditor)
|
||||
ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch)
|
||||
ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool)
|
||||
ON_COMMAND(ID_DISPLAY_SHOWHELPERS, OnShowHelpers)
|
||||
ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView)
|
||||
ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor)
|
||||
ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch)
|
||||
ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool)
|
||||
ON_COMMAND(ID_TERRAIN_TIMEOFDAY, OnTimeOfDay)
|
||||
ON_COMMAND(ID_TERRAIN_TIMEOFDAYBUTTON, OnTimeOfDay)
|
||||
|
||||
@@ -1898,14 +1882,6 @@ BOOL CCryEditApp::InitInstance()
|
||||
CWipFeatureManager::Init();
|
||||
#endif
|
||||
|
||||
if (GetIEditor()->IsInMatEditMode())
|
||||
{
|
||||
m_pMatEditDlg = new CMatEditMainDlg(QStringLiteral("Material Editor"));
|
||||
m_pEditor->InitFinished();
|
||||
m_pMatEditDlg->show();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_bConsoleMode && !m_bPreviewMode)
|
||||
{
|
||||
GetIEditor()->UpdateViews();
|
||||
@@ -2753,15 +2729,6 @@ void CCryEditApp::OnEditDelete()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendants)
|
||||
{
|
||||
// If Edit tool active cannot delete object.
|
||||
if (GetIEditor()->GetEditTool())
|
||||
{
|
||||
if (GetIEditor()->GetEditTool()->OnKeyDown(GetIEditor()->GetViewManager()->GetView(0), VK_DELETE, 0, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GetIEditor()->BeginUndo();
|
||||
CUndo undo("Delete Selected Object");
|
||||
GetIEditor()->GetObjectManager()->DeleteSelection();
|
||||
@@ -2770,75 +2737,6 @@ void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendant
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
}
|
||||
|
||||
void CCryEditApp::OnEditClone()
|
||||
{
|
||||
if (!GetIEditor()->IsNewViewportInteractionModelEnabled())
|
||||
{
|
||||
if (GetIEditor()->GetObjectManager()->GetSelection()->IsEmpty())
|
||||
{
|
||||
QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(),
|
||||
QObject::tr("You have to select objects before you can clone them!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor is being edited.
|
||||
if (QApplication::focusWidget())
|
||||
{
|
||||
QApplication::focusWidget()->clearFocus();
|
||||
}
|
||||
|
||||
CEditTool* tool = GetIEditor()->GetEditTool();
|
||||
if (tool && qobject_cast<CObjectCloneTool*>(tool))
|
||||
{
|
||||
((CObjectCloneTool*)tool)->Accept();
|
||||
}
|
||||
|
||||
CObjectCloneTool* cloneTool = new CObjectCloneTool;
|
||||
GetIEditor()->SetEditTool(cloneTool);
|
||||
GetIEditor()->SetModifiedFlag();
|
||||
GetIEditor()->SetModifiedModule(eModifiedBrushes);
|
||||
|
||||
// Accept the clone operation if users didn't choose to stick duplicated entities to the cursor
|
||||
// This setting can be changed in the global preference of the editor
|
||||
if (!gSettings.deepSelectionSettings.bStickDuplicate)
|
||||
{
|
||||
cloneTool->Accept();
|
||||
GetIEditor()->GetSelection()->FinishChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCryEditApp::OnEditEscape()
|
||||
{
|
||||
if (!GetIEditor()->IsNewViewportInteractionModelEnabled())
|
||||
{
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
// Abort current operation.
|
||||
if (pEditTool)
|
||||
{
|
||||
// If Edit tool active cannot delete object.
|
||||
CViewport* vp = GetIEditor()->GetActiveView();
|
||||
if (GetIEditor()->GetEditTool()->OnKeyDown(vp, VK_ESCAPE, 0, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetIEditor()->GetEditMode() == eEditModeSelectArea)
|
||||
{
|
||||
GetIEditor()->SetEditMode(eEditModeSelect);
|
||||
}
|
||||
|
||||
// Disable current tool.
|
||||
GetIEditor()->SetEditTool(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear selection on escape.
|
||||
GetIEditor()->ClearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCryEditApp::OnMoveObject()
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -2905,51 +2803,6 @@ void CCryEditApp::OnEditmodeScale()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnEditToolLink()
|
||||
{
|
||||
// TODO: Add your command handler code here
|
||||
if (qobject_cast<CLinkTool*>(GetIEditor()->GetEditTool()))
|
||||
{
|
||||
GetIEditor()->SetEditTool(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->SetEditTool(new CLinkTool());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateEditToolLink(QAction* action)
|
||||
{
|
||||
if (!GetIEditor()->GetDocument())
|
||||
{
|
||||
action->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
action->setEnabled(GetIEditor()->GetDocument()->IsDocumentReady());
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
action->setChecked(qobject_cast<CLinkTool*>(pEditTool) != nullptr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnEditToolUnlink()
|
||||
{
|
||||
CUndo undo("Unlink Object(s)");
|
||||
CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
|
||||
for (int i = 0; i < pSelection->GetCount(); i++)
|
||||
{
|
||||
CBaseObject* pBaseObj = pSelection->GetObject(i);
|
||||
pBaseObj->DetachThis();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateEditToolUnlink(QAction* action)
|
||||
{
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnEditmodeSelect()
|
||||
{
|
||||
@@ -3045,14 +2898,6 @@ void CCryEditApp::OnUpdateEditmodeScale(QAction* action)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateEditmodeVertexSnapping(QAction* action)
|
||||
{
|
||||
Q_ASSERT(action->isCheckable());
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
action->setChecked(qobject_cast<CVertexSnappingModeTool*>(pEditTool) != nullptr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnObjectSetArea()
|
||||
{
|
||||
@@ -3202,19 +3047,6 @@ void CCryEditApp::OnObjectSetHeight()
|
||||
}
|
||||
}
|
||||
|
||||
void CCryEditApp::OnObjectVertexSnapping()
|
||||
{
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
if (qobject_cast<CVertexSnappingModeTool*>(pEditTool))
|
||||
{
|
||||
GetIEditor()->SetEditTool(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->SetEditTool("EditTool.VertexSnappingMode");
|
||||
}
|
||||
}
|
||||
|
||||
void CCryEditApp::OnObjectmodifyFreeze()
|
||||
{
|
||||
// Freeze selection.
|
||||
@@ -3519,14 +3351,6 @@ void CCryEditApp::OnUpdateSelected(QAction* action)
|
||||
action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnAlignObject()
|
||||
{
|
||||
// Align pick callback will release itself.
|
||||
CAlignPickCallback* alignCallback = new CAlignPickCallback;
|
||||
GetIEditor()->PickObject(alignCallback, 0, "Align to Object");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnAlignToGrid()
|
||||
{
|
||||
@@ -3547,46 +3371,8 @@ void CCryEditApp::OnAlignToGrid()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateAlignObject(QAction* action)
|
||||
{
|
||||
Q_ASSERT(action->isCheckable());
|
||||
action->setChecked(CAlignPickCallback::IsActive());
|
||||
|
||||
action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnAlignToVoxel()
|
||||
{
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
if (qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr)
|
||||
{
|
||||
GetIEditor()->SetEditTool(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->SetEditTool(new CVoxelAligningTool());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnUpdateAlignToVoxel(QAction* action)
|
||||
{
|
||||
Q_ASSERT(action->isCheckable());
|
||||
CEditTool* pEditTool = GetIEditor()->GetEditTool();
|
||||
action->setChecked(qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr);
|
||||
|
||||
action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty());
|
||||
}
|
||||
|
||||
void CCryEditApp::OnShowHelpers()
|
||||
{
|
||||
CEditTool* pEditTool(GetIEditor()->GetEditTool());
|
||||
if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
|
||||
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
|
||||
}
|
||||
@@ -5212,12 +4998,6 @@ void CCryEditApp::OnOpenUICanvasEditor()
|
||||
QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnMaterialPicktool()
|
||||
{
|
||||
GetIEditor()->SetEditTool("EditTool.PickMaterial");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCryEditApp::OnTimeOfDay()
|
||||
{
|
||||
@@ -5372,12 +5152,6 @@ void CCryEditApp::OnOpenQuickAccessBar()
|
||||
return;
|
||||
}
|
||||
|
||||
CEditTool* pEditTool(GetIEditor()->GetEditTool());
|
||||
if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QRect geo = m_pQuickAccessBar->geometry();
|
||||
geo.moveCenter(MainWindow::instance()->geometry().center());
|
||||
m_pQuickAccessBar->setGeometry(geo);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
class CCryDocManager;
|
||||
class CQuickAccessBar;
|
||||
class CMatEditMainDlg;
|
||||
class CCryEditDoc;
|
||||
class CEditCommandLineInfo;
|
||||
class CMainFrame;
|
||||
@@ -225,16 +224,9 @@ public:
|
||||
void OnEditmodeMove();
|
||||
void OnEditmodeRotate();
|
||||
void OnEditmodeScale();
|
||||
void OnEditToolLink();
|
||||
void OnUpdateEditToolLink(QAction* action);
|
||||
void OnEditToolUnlink();
|
||||
void OnUpdateEditToolUnlink(QAction* action);
|
||||
void OnEditmodeSelect();
|
||||
void OnEditEscape();
|
||||
void OnObjectSetArea();
|
||||
void OnObjectSetHeight();
|
||||
void OnObjectVertexSnapping();
|
||||
void OnUpdateEditmodeVertexSnapping(QAction* action);
|
||||
void OnUpdateEditmodeSelect(QAction* action);
|
||||
void OnUpdateEditmodeMove(QAction* action);
|
||||
void OnUpdateEditmodeRotate(QAction* action);
|
||||
@@ -252,16 +244,11 @@ public:
|
||||
void OnUpdateSelectAxisY(QAction* action);
|
||||
void OnUpdateSelectAxisZ(QAction* action);
|
||||
void OnUndo();
|
||||
void OnEditClone();
|
||||
void OnSelectionSave();
|
||||
void OnOpenAssetImporter();
|
||||
void OnSelectionLoad();
|
||||
void OnUpdateSelected(QAction* action);
|
||||
void OnAlignObject();
|
||||
void OnAlignToVoxel();
|
||||
void OnAlignToGrid();
|
||||
void OnUpdateAlignObject(QAction* action);
|
||||
void OnUpdateAlignToVoxel(QAction* action);
|
||||
void OnLockSelection();
|
||||
void OnEditLevelData();
|
||||
void OnFileEditLogFile();
|
||||
@@ -367,7 +354,6 @@ private:
|
||||
//! Autotest mode: Special mode meant for automated testing, things like blocking dialogs or error report windows won't appear
|
||||
bool m_bAutotestMode = false;
|
||||
|
||||
CMatEditMainDlg* m_pMatEditDlg = nullptr;
|
||||
CConsoleDialog* m_pConsoleDialog = nullptr;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
@@ -499,7 +485,6 @@ private:
|
||||
void OnOpenAudioControlsEditor();
|
||||
void OnOpenUICanvasEditor();
|
||||
void OnGotoViewportSearch();
|
||||
void OnMaterialPicktool();
|
||||
void OnTimeOfDay();
|
||||
void OnChangeGameSpec(UINT nID);
|
||||
void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable);
|
||||
|
||||
@@ -279,7 +279,6 @@ void CCryEditDoc::DeleteContents()
|
||||
// [LY-90904] move this to the EditorVegetationManager component
|
||||
InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData);
|
||||
|
||||
GetIEditor()->SetEditTool(0); // Turn off any active edit tools.
|
||||
GetIEditor()->SetEditMode(eEditModeSelect);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -216,7 +216,6 @@ protected:
|
||||
void OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAssetId, const AzFramework::SliceInstantiationTicket& /*ticket*/) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QString m_strMasterCDFolder;
|
||||
bool m_bLoadFailed;
|
||||
QColor m_waterColor;
|
||||
XmlNodeRef m_fogTemplate;
|
||||
|
||||
@@ -1,123 +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 "ButtonsPanel.h"
|
||||
|
||||
// Qt
|
||||
#include <QGridLayout>
|
||||
|
||||
// Editor
|
||||
#include "Controls/ToolButton.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CButtonsPanel dialog
|
||||
CButtonsPanel::CButtonsPanel(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
CButtonsPanel::~CButtonsPanel()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CButtonsPanel::AddButton(const SButtonInfo& button)
|
||||
{
|
||||
SButton b;
|
||||
b.info = button;
|
||||
m_buttons.push_back(b);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CButtonsPanel::AddButton(const QString& name, const QString& toolClass)
|
||||
{
|
||||
SButtonInfo bi;
|
||||
bi.name = name;
|
||||
bi.toolClassName = toolClass;
|
||||
AddButton(bi);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CButtonsPanel::AddButton(const QString& name, const QMetaObject* pToolClass)
|
||||
{
|
||||
SButtonInfo bi;
|
||||
bi.name = name;
|
||||
bi.pToolClass = pToolClass;
|
||||
AddButton(bi);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CButtonsPanel::ClearButtons()
|
||||
{
|
||||
auto buttons = layout()->findChildren<QEditorToolButton*>();
|
||||
foreach(auto button, buttons)
|
||||
{
|
||||
layout()->removeWidget(button);
|
||||
delete button;
|
||||
}
|
||||
m_buttons.clear();
|
||||
}
|
||||
|
||||
void CButtonsPanel::UncheckAll()
|
||||
{
|
||||
for (auto& button : m_buttons)
|
||||
{
|
||||
button.pButton->SetSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CButtonsPanel::OnInitDialog()
|
||||
{
|
||||
auto layout = new QGridLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
layout->setMargin(4);
|
||||
layout->setHorizontalSpacing(4);
|
||||
layout->setVerticalSpacing(1);
|
||||
|
||||
// Create Buttons.
|
||||
int index = 0;
|
||||
for (auto& button : m_buttons)
|
||||
{
|
||||
button.pButton = new QEditorToolButton(this);
|
||||
button.pButton->setObjectName(button.info.name);
|
||||
button.pButton->setText(button.info.name);
|
||||
button.pButton->SetNeedDocument(button.info.bNeedDocument);
|
||||
button.pButton->setToolTip(button.info.toolTip);
|
||||
|
||||
if (button.info.pToolClass)
|
||||
{
|
||||
button.pButton->SetToolClass(button.info.pToolClass, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str());
|
||||
}
|
||||
else if (!button.info.toolClassName.isEmpty())
|
||||
{
|
||||
button.pButton->SetToolName(button.info.toolClassName, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str());
|
||||
}
|
||||
|
||||
layout->addWidget(button.pButton, index / 2, index % 2);
|
||||
connect(button.pButton, &QEditorToolButton::clicked, this, [&]() { OnButtonPressed(button.info); });
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
void CButtonsPanel::EnableButton(const QString& buttonName, bool enable)
|
||||
{
|
||||
for (auto& button : m_buttons)
|
||||
{
|
||||
if (button.pButton->objectName() == buttonName)
|
||||
{
|
||||
button.pButton->setEnabled(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <Dialogs/moc_ButtonsPanel.cpp>
|
||||
@@ -1,76 +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_DIALOGS_BUTTONSPANEL_H
|
||||
#define CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
class QEditorToolButton;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Panel with custom auto arranged buttons
|
||||
class CButtonsPanel
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
struct SButtonInfo
|
||||
{
|
||||
QString name;
|
||||
QString toolClassName;
|
||||
QString toolUserDataKey;
|
||||
std::string toolUserData;
|
||||
QString toolTip;
|
||||
bool bNeedDocument;
|
||||
const QMetaObject* pToolClass;
|
||||
|
||||
SButtonInfo()
|
||||
: pToolClass(nullptr)
|
||||
, bNeedDocument(true) {};
|
||||
};
|
||||
|
||||
CButtonsPanel(QWidget* parent);
|
||||
virtual ~CButtonsPanel();
|
||||
|
||||
virtual void AddButton(const SButtonInfo& button);
|
||||
virtual void AddButton(const QString& name, const QString& toolClass);
|
||||
virtual void AddButton(const QString& name, const QMetaObject* pToolClass);
|
||||
virtual void EnableButton(const QString& buttonName, bool disable);
|
||||
virtual void ClearButtons();
|
||||
|
||||
virtual void OnButtonPressed([[maybe_unused]] const SButtonInfo& button) {};
|
||||
virtual void UncheckAll();
|
||||
|
||||
protected:
|
||||
void ReleaseGuiButtons();
|
||||
|
||||
virtual void OnInitDialog();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SButton
|
||||
{
|
||||
SButtonInfo info;
|
||||
QEditorToolButton* pButton;
|
||||
SButton()
|
||||
: pButton(nullptr) {};
|
||||
};
|
||||
|
||||
std::vector<SButton> m_buttons;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +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.
|
||||
|
||||
// Description : Object edit mode describe viewport input behavior when operating on objects.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H
|
||||
#define CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H
|
||||
#pragma once
|
||||
|
||||
// {87109FED-BDB5-4874-936D-338400079F58}
|
||||
DEFINE_GUID(OBJECT_MODE_GUID, 0x87109fed, 0xbdb5, 0x4874, 0x93, 0x6d, 0x33, 0x84, 0x0, 0x7, 0x9f, 0x58);
|
||||
|
||||
#include "EditTool.h"
|
||||
|
||||
class CBaseObject;
|
||||
class CDeepSelection;
|
||||
/*!
|
||||
* CObjectMode is an abstract base class for All Editing Tools supported by Editor.
|
||||
* Edit tools handle specific editing modes in viewports.
|
||||
*/
|
||||
class SANDBOX_API CObjectMode
|
||||
: public CEditTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE CObjectMode(QObject* parent = nullptr);
|
||||
virtual ~CObjectMode();
|
||||
|
||||
static const GUID& GetClassID() { return OBJECT_MODE_GUID; }
|
||||
|
||||
// Registration function.
|
||||
static void RegisterTool(CRegistrationContext& rc);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CEditTool implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {};
|
||||
virtual void EndEditParams();
|
||||
virtual void Display(struct DisplayContext& dc);
|
||||
virtual void DisplaySelectionPreview(struct DisplayContext& dc);
|
||||
virtual void DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject);
|
||||
void DisplayExtraLightInfo(struct DisplayContext& dc);
|
||||
|
||||
virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
|
||||
virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags);
|
||||
virtual bool OnKeyUp(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags);
|
||||
virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; };
|
||||
|
||||
virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, QPoint& p0, QPoint& p1, const Vec3& value) override;
|
||||
|
||||
bool IsUpdateUIPanel() override { return true; }
|
||||
|
||||
protected:
|
||||
enum ECommandMode
|
||||
{
|
||||
NothingMode = 0,
|
||||
ScrollZoomMode,
|
||||
SelectMode,
|
||||
MoveMode,
|
||||
RotateMode,
|
||||
ScaleMode,
|
||||
ScrollMode,
|
||||
ZoomMode,
|
||||
};
|
||||
|
||||
virtual bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnRButtonDown(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnRButtonUp(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnMButtonDown(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point);
|
||||
virtual bool OnMouseLeave(CViewport* view);
|
||||
|
||||
void SetCommandMode(ECommandMode mode) { m_commandMode = mode; }
|
||||
ECommandMode GetCommandMode() const { return m_commandMode; }
|
||||
|
||||
//! Ctrl-Click in move mode to move selected objects to given pos.
|
||||
void MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point);
|
||||
void SetObjectCursor(CViewport* view, CBaseObject* hitObj, bool bChangeNow = false);
|
||||
|
||||
virtual void DeleteThis() { delete this; };
|
||||
|
||||
void UpdateStatusText();
|
||||
void AwakeObjectAtPoint(CViewport* view, const QPoint& point);
|
||||
|
||||
void HideMoveByFaceNormGizmo();
|
||||
void HandleMoveByFaceNormal(HitContext& hitInfo);
|
||||
void UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject);
|
||||
|
||||
protected:
|
||||
|
||||
bool m_openContext;
|
||||
|
||||
private:
|
||||
void CheckDeepSelection(HitContext& hitContext, CViewport* view);
|
||||
Vec3& GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale);
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QPoint m_cMouseDownPos;
|
||||
bool m_bDragThresholdExceeded;
|
||||
ECommandMode m_commandMode;
|
||||
|
||||
GUID m_MouseOverObject;
|
||||
typedef std::vector<GUID> TGuidContainer;
|
||||
TGuidContainer m_PreviewGUIDs;
|
||||
|
||||
_smart_ptr<CDeepSelection> m_pDeepSelection;
|
||||
|
||||
bool m_bMoveByFaceNormManipShown;
|
||||
CBaseObject* m_pHitObject;
|
||||
|
||||
bool m_bTransformChanged;
|
||||
|
||||
QPoint m_prevMousePos = QPoint(0, 0);
|
||||
|
||||
Vec3 m_lastValidMoveVector = Vec3(0, 0, 0);
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H
|
||||
@@ -1,430 +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"
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#include <InitGuid.h>
|
||||
#endif
|
||||
|
||||
#include "VertexSnappingModeTool.h"
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
#include "Viewport.h"
|
||||
#include "SurfaceInfoPicker.h"
|
||||
#include "Material/Material.h"
|
||||
#include "Util/KDTree.h"
|
||||
|
||||
|
||||
// {3e008046-9269-41d7-82e2-07ffd7254c10}
|
||||
DEFINE_GUID(VERTEXSNAPPING_MODE_GUID, 0x3e008046, 0x9269, 0x41d7, 0x82, 0xe2, 0x07, 0xff, 0xd7, 0x25, 0x4c, 0x10);
|
||||
|
||||
bool FindNearestVertex(CBaseObject* pObject, CKDTree* pTree, const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, Vec3& outPos, Vec3& vOutHitPosOnCube)
|
||||
{
|
||||
Matrix34 worldInvTM = pObject->GetWorldTM().GetInverted();
|
||||
Vec3 vRaySrc = worldInvTM.TransformPoint(vWorldRaySrc);
|
||||
Vec3 vRayDir = worldInvTM.TransformVector(vWorldRayDir);
|
||||
Vec3 vLocalCameraPos = worldInvTM.TransformPoint(gEnv->pRenderer->GetCamera().GetPosition());
|
||||
Vec3 vPos;
|
||||
Vec3 vHitPosOnCube;
|
||||
|
||||
if (pTree)
|
||||
{
|
||||
if (pTree->FindNearestVertex(vRaySrc, vRayDir, gSettings.vertexSnappingSettings.vertexCubeSize, vLocalCameraPos, vPos, vHitPosOnCube))
|
||||
{
|
||||
outPos = pObject->GetWorldTM().TransformPoint(vPos);
|
||||
vOutHitPosOnCube = pObject->GetWorldTM().TransformPoint(vHitPosOnCube);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for objects without verts, the pivot is the nearest vertex
|
||||
// return true if the ray hits the bounding box
|
||||
outPos = pObject->GetWorldPos();
|
||||
|
||||
AABB bbox;
|
||||
pObject->GetBoundBox(bbox);
|
||||
if (bbox.IsContainPoint(vWorldRaySrc))
|
||||
{
|
||||
// if ray starts inside bounding box, reject cases where pivot is behind the ray
|
||||
float hitDistAlongRay = vWorldRayDir.Dot(outPos - vWorldRaySrc);
|
||||
if (hitDistAlongRay >= 0.f)
|
||||
{
|
||||
vHitPosOnCube = vWorldRaySrc + (vWorldRayDir * hitDistAlongRay);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, bbox, vOutHitPosOnCube))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CVertexSnappingModeTool::CVertexSnappingModeTool()
|
||||
{
|
||||
m_modeStatus = eVSS_SelectFirstVertex;
|
||||
m_bHit = false;
|
||||
}
|
||||
|
||||
CVertexSnappingModeTool::~CVertexSnappingModeTool()
|
||||
{
|
||||
std::map<CBaseObjectPtr, CKDTree*>::iterator ii = m_ObjectKdTreeMap.begin();
|
||||
for (; ii != m_ObjectKdTreeMap.end(); ++ii)
|
||||
{
|
||||
delete ii->second;
|
||||
}
|
||||
}
|
||||
|
||||
const GUID& CVertexSnappingModeTool::GetClassID()
|
||||
{
|
||||
return VERTEXSNAPPING_MODE_GUID;
|
||||
}
|
||||
|
||||
void CVertexSnappingModeTool::RegisterTool(CRegistrationContext& rc)
|
||||
{
|
||||
rc.pClassFactory->RegisterClass(new CQtViewClass<CVertexSnappingModeTool>("EditTool.VertexSnappingMode", "Select", ESYSTEM_CLASS_EDITTOOL));
|
||||
}
|
||||
|
||||
bool CVertexSnappingModeTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags)
|
||||
{
|
||||
CBaseObjectPtr pExcludedObject = NULL;
|
||||
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex)
|
||||
{
|
||||
pExcludedObject = m_SelectionInfo.m_pObject;
|
||||
}
|
||||
|
||||
m_bHit = HitTest(view, point, pExcludedObject, m_vHitVertex, m_pHitObject, m_Objects);
|
||||
|
||||
if (event == eMouseLDown && m_bHit && m_pHitObject && m_modeStatus == eVSS_SelectFirstVertex)
|
||||
{
|
||||
m_modeStatus = eVSS_MoveSelectVertexToAnotherVertex;
|
||||
m_SelectionInfo.m_pObject = m_pHitObject;
|
||||
m_SelectionInfo.m_vPos = m_vHitVertex;
|
||||
|
||||
GetIEditor()->BeginUndo();
|
||||
m_pHitObject->StoreUndo("Vertex Snapping", true);
|
||||
|
||||
view->SetCapture();
|
||||
}
|
||||
|
||||
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex)
|
||||
{
|
||||
if (event == eMouseLUp)
|
||||
{
|
||||
m_modeStatus = eVSS_SelectFirstVertex;
|
||||
|
||||
GetIEditor()->AcceptUndo("Vertex Snapping");
|
||||
view->ReleaseMouse();
|
||||
}
|
||||
else if ((flags & MK_LBUTTON) && event == eMouseMove)
|
||||
{
|
||||
Vec3 vOffset = m_SelectionInfo.m_pObject->GetWorldPos() - m_SelectionInfo.m_vPos;
|
||||
m_SelectionInfo.m_pObject->SetWorldPos(m_vHitVertex + vOffset);
|
||||
m_SelectionInfo.m_vPos = m_SelectionInfo.m_pObject->GetWorldPos() - vOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVertexSnappingModeTool::HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects)
|
||||
{
|
||||
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
|
||||
{
|
||||
m_DebugBoxes.clear();
|
||||
}
|
||||
|
||||
pOutHitObject = NULL;
|
||||
outObjects.clear();
|
||||
|
||||
//
|
||||
// Collect valid objects that mouse is over
|
||||
//
|
||||
|
||||
CSurfaceInfoPicker picker;
|
||||
CSurfaceInfoPicker::CExcludedObjects excludedObjects;
|
||||
if (pExcludedObj)
|
||||
{
|
||||
excludedObjects.Add(pExcludedObj);
|
||||
}
|
||||
|
||||
int nPickFlag = CSurfaceInfoPicker::ePOG_Entity;
|
||||
|
||||
std::vector<CBaseObjectPtr> penetratedObjects;
|
||||
if (!picker.PickByAABB(point, nPickFlag, view, &excludedObjects, &penetratedObjects))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0, iCount(penetratedObjects.size()); i < iCount; ++i)
|
||||
{
|
||||
CMaterial* pMaterial = penetratedObjects[i]->GetMaterial();
|
||||
if (pMaterial)
|
||||
{
|
||||
QString matName = pMaterial->GetName();
|
||||
if (!QString::compare(matName, "Objects/sky/forest_sky_dome", Qt::CaseInsensitive))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
outObjects.push_back(penetratedObjects[i]);
|
||||
}
|
||||
|
||||
//
|
||||
// Find the best vertex.
|
||||
//
|
||||
|
||||
Vec3 vWorldRaySrc, vWorldRayDir;
|
||||
view->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir);
|
||||
|
||||
std::vector<CBaseObjectPtr>::iterator ii = outObjects.begin();
|
||||
float fNearestDist = 3e10f;
|
||||
Vec3 vNearestPos;
|
||||
CBaseObjectPtr pNearestObject = NULL;
|
||||
for (ii = outObjects.begin(); ii != outObjects.end(); ++ii)
|
||||
{
|
||||
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
|
||||
{
|
||||
// add to debug boxes: the penetrated nodes of each object's kd-tree
|
||||
if (auto pTree = GetKDTree(*ii))
|
||||
{
|
||||
Matrix34 invWorldTM = (*ii)->GetWorldTM().GetInverted();
|
||||
int nIndex = m_DebugBoxes.size();
|
||||
|
||||
Vec3 vLocalRaySrc = invWorldTM.TransformPoint(vWorldRaySrc);
|
||||
Vec3 vLocalRayDir = invWorldTM.TransformVector(vWorldRayDir);
|
||||
pTree->GetPenetratedBoxes(vLocalRaySrc, vLocalRayDir, m_DebugBoxes);
|
||||
for (int i = nIndex; i < m_DebugBoxes.size(); ++i)
|
||||
{
|
||||
m_DebugBoxes[i].SetTransformedAABB((*ii)->GetWorldTM(), m_DebugBoxes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find the nearest vertex on this object
|
||||
Vec3 vPos, vHitPosOnCube;
|
||||
if (FindNearestVertex(*ii, GetKDTree(*ii), vWorldRaySrc, vWorldRayDir, vPos, vHitPosOnCube))
|
||||
{
|
||||
// is this the best so far?
|
||||
float fDistance = vHitPosOnCube.GetDistance(vWorldRaySrc);
|
||||
if (fDistance < fNearestDist)
|
||||
{
|
||||
fNearestDist = fDistance;
|
||||
vNearestPos = vPos;
|
||||
pNearestObject = *ii;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fNearestDist < 3e10f)
|
||||
{
|
||||
outHitPos = vNearestPos;
|
||||
pOutHitObject = pNearestObject;
|
||||
}
|
||||
|
||||
// if the mouse is over the object's pivot, use that instead of a vertex
|
||||
if (pOutHitObject)
|
||||
{
|
||||
Vec3 vPivotPos = pOutHitObject->GetWorldPos();
|
||||
Vec3 vPivotBox = GetCubeSize(view, pOutHitObject->GetWorldPos());
|
||||
AABB pivotAABB(vPivotPos - vPivotBox, vPivotPos + vPivotBox);
|
||||
Vec3 vPosOnPivotCube;
|
||||
if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, pivotAABB, vPosOnPivotCube))
|
||||
{
|
||||
outHitPos = vPivotPos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pOutHitObject && pOutHitObject == pNearestObject;
|
||||
}
|
||||
|
||||
Vec3 CVertexSnappingModeTool::GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const
|
||||
{
|
||||
if (!pView)
|
||||
{
|
||||
return Vec3(0, 0, 0);
|
||||
}
|
||||
float fScreenFactor = pView->GetScreenScaleFactor(pos);
|
||||
return gSettings.vertexSnappingSettings.vertexCubeSize * Vec3(fScreenFactor, fScreenFactor, fScreenFactor);
|
||||
}
|
||||
|
||||
void CVertexSnappingModeTool::Display(struct DisplayContext& dc)
|
||||
{
|
||||
const ColorB SnappedColor(0xFF00FF00);
|
||||
const ColorB PivotColor(0xFF2020FF);
|
||||
const ColorB VertexColor(0xFFFFAAAA);
|
||||
|
||||
// draw all objects under mouse
|
||||
dc.SetColor(VertexColor);
|
||||
for (int i = 0, iCount(m_Objects.size()); i < iCount; ++i)
|
||||
{
|
||||
AABB worldAABB;
|
||||
m_Objects[i]->GetBoundBox(worldAABB);
|
||||
if (!dc.view->IsBoundsVisible(worldAABB))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto pStatObj = m_Objects[i]->GetIStatObj())
|
||||
{
|
||||
DrawVertexCubes(dc, m_Objects[i]->GetWorldTM(), pStatObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.DrawWireBox(worldAABB.min, worldAABB.max);
|
||||
}
|
||||
}
|
||||
|
||||
// draw object being moved
|
||||
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex && m_SelectionInfo.m_pObject)
|
||||
{
|
||||
dc.SetColor(QColor(0xaa, 0xaa, 0xaa));
|
||||
if (auto pStatObj = m_SelectionInfo.m_pObject->GetIStatObj())
|
||||
{
|
||||
DrawVertexCubes(dc, m_SelectionInfo.m_pObject->GetWorldTM(), pStatObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
AABB bounds;
|
||||
m_SelectionInfo.m_pObject->GetBoundBox(bounds);
|
||||
dc.DrawWireBox(bounds.min, bounds.max);
|
||||
}
|
||||
}
|
||||
|
||||
// draw pivot of hit object
|
||||
if (m_pHitObject && (!m_bHit || m_bHit && !m_pHitObject->GetWorldPos().IsEquivalent(m_vHitVertex, 0.001f)))
|
||||
{
|
||||
dc.SetColor(PivotColor);
|
||||
dc.DepthTestOff();
|
||||
|
||||
Vec3 vBoxSize = GetCubeSize(dc.view, m_pHitObject->GetWorldPos()) * 1.2f;
|
||||
AABB vertexBox(m_pHitObject->GetWorldPos() - vBoxSize, m_pHitObject->GetWorldPos() + vBoxSize);
|
||||
dc.DrawBall((vertexBox.min + vertexBox.max) * 0.5f, (vertexBox.max.x - vertexBox.min.x) * 0.5f);
|
||||
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
// draw the vertex (or pivot) that's being hit
|
||||
if (m_bHit)
|
||||
{
|
||||
dc.DepthTestOff();
|
||||
dc.SetColor(SnappedColor);
|
||||
Vec3 vBoxSize = GetCubeSize(dc.view, m_vHitVertex);
|
||||
if (m_vHitVertex.IsEquivalent(m_pHitObject->GetWorldPos(), 0.001f))
|
||||
{
|
||||
dc.DrawBall(m_vHitVertex, vBoxSize.x * 1.2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.DrawSolidBox(m_vHitVertex - vBoxSize, m_vHitVertex + vBoxSize);
|
||||
}
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
// draw wireframe of hit object
|
||||
if (m_pHitObject && m_pHitObject->GetIStatObj())
|
||||
{
|
||||
SGeometryDebugDrawInfo dd;
|
||||
dd.tm = m_pHitObject->GetWorldTM();
|
||||
dd.color = ColorB(250, 0, 250, 30);
|
||||
dd.lineColor = ColorB(255, 255, 0, 160);
|
||||
dd.bExtrude = true;
|
||||
m_pHitObject->GetIStatObj()->DebugDraw(dd);
|
||||
}
|
||||
|
||||
// draw debug boxes
|
||||
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
|
||||
{
|
||||
ColorB boxColor(40, 40, 40);
|
||||
for (int i = 0, iCount(m_DebugBoxes.size()); i < iCount; ++i)
|
||||
{
|
||||
dc.SetColor(boxColor);
|
||||
boxColor += ColorB(25, 25, 25);
|
||||
dc.DrawWireBox(m_DebugBoxes[i].min, m_DebugBoxes[i].max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVertexSnappingModeTool::DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj)
|
||||
{
|
||||
if (!pStatObj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IIndexedMesh* pIndexedMesh = pStatObj->GetIndexedMesh();
|
||||
if (pIndexedMesh)
|
||||
{
|
||||
IIndexedMesh::SMeshDescription md;
|
||||
pIndexedMesh->GetMeshDescription(md);
|
||||
for (int k = 0; k < md.m_nVertCount; ++k)
|
||||
{
|
||||
Vec3 vPos(0, 0, 0);
|
||||
if (md.m_pVerts)
|
||||
{
|
||||
vPos = md.m_pVerts[k];
|
||||
}
|
||||
else if (md.m_pVertsF16)
|
||||
{
|
||||
vPos = md.m_pVertsF16[k].ToVec3();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
vPos = tm.TransformPoint(vPos);
|
||||
Vec3 vBoxSize = GetCubeSize(dc.view, vPos);
|
||||
if (!m_bHit || !m_vHitVertex.IsEquivalent(vPos, 0.001f))
|
||||
{
|
||||
dc.DrawSolidBox(vPos - vBoxSize, vPos + vBoxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, iSubStatObjNum(pStatObj->GetSubObjectCount()); i < iSubStatObjNum; ++i)
|
||||
{
|
||||
IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(i);
|
||||
if (pSubObj)
|
||||
{
|
||||
DrawVertexCubes(dc, tm * pSubObj->localTM, pSubObj->pStatObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CKDTree* CVertexSnappingModeTool::GetKDTree(CBaseObject* pObject)
|
||||
{
|
||||
auto existingTree = m_ObjectKdTreeMap.find(pObject);
|
||||
if (existingTree != m_ObjectKdTreeMap.end())
|
||||
{
|
||||
return existingTree->second;
|
||||
}
|
||||
|
||||
// Don't build a kd-tree for objects without verts
|
||||
CKDTree* pTree = nullptr;
|
||||
if (auto pStatObj = pObject->GetIStatObj())
|
||||
{
|
||||
pTree = new CKDTree();
|
||||
pTree->Build(pObject->GetIStatObj());
|
||||
}
|
||||
|
||||
m_ObjectKdTreeMap[pObject] = pTree;
|
||||
return pTree;
|
||||
}
|
||||
|
||||
#include <EditMode/moc_VertexSnappingModeTool.cpp>
|
||||
@@ -1,91 +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_EDITMODE_VERTEXSNAPPINGMODETOOL_H
|
||||
#define CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H
|
||||
#pragma once
|
||||
|
||||
#include "EditTool.h"
|
||||
#include "Objects/BaseObject.h"
|
||||
|
||||
class CKDTree;
|
||||
struct IDisplayViewport;
|
||||
|
||||
class CVertexSnappingModeTool
|
||||
: public CEditTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE CVertexSnappingModeTool();
|
||||
~CVertexSnappingModeTool();
|
||||
|
||||
static const GUID& GetClassID();
|
||||
|
||||
static void RegisterTool(CRegistrationContext& rc);
|
||||
|
||||
void Display(DisplayContext& dc);
|
||||
bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
|
||||
|
||||
protected:
|
||||
|
||||
void DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj);
|
||||
void DeleteThis(){ delete this; }
|
||||
Vec3 GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const;
|
||||
|
||||
private:
|
||||
|
||||
using CEditTool::HitTest;
|
||||
bool HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects);
|
||||
CKDTree* GetKDTree(CBaseObject* pObject);
|
||||
|
||||
enum EVertexSnappingStatus
|
||||
{
|
||||
eVSS_SelectFirstVertex,
|
||||
eVSS_MoveSelectVertexToAnotherVertex
|
||||
};
|
||||
EVertexSnappingStatus m_modeStatus;
|
||||
|
||||
struct SSelectionInfo
|
||||
{
|
||||
SSelectionInfo()
|
||||
{
|
||||
m_pObject = NULL;
|
||||
m_vPos = Vec3(0, 0, 0);
|
||||
}
|
||||
CBaseObjectPtr m_pObject;
|
||||
Vec3 m_vPos;
|
||||
};
|
||||
|
||||
/// Info on object being moved (when in eVSS_MoveSelectVertexToAnotherVertex mode).
|
||||
SSelectionInfo m_SelectionInfo;
|
||||
|
||||
/// Objects that mouse is over
|
||||
std::vector<CBaseObjectPtr> m_Objects;
|
||||
|
||||
/// Position of vertex that mouse is hitting.
|
||||
/// Invalid when m_bHit is false.
|
||||
Vec3 m_vHitVertex;
|
||||
|
||||
/// Whether the mouse hit test succeeded
|
||||
bool m_bHit;
|
||||
|
||||
/// Object that mouse is hitting
|
||||
CBaseObjectPtr m_pHitObject;
|
||||
|
||||
/// Boxes to render for debug drawing
|
||||
std::vector<AABB> m_DebugBoxes;
|
||||
|
||||
/// For each object, a tree containing its vertices.
|
||||
std::map<CBaseObjectPtr, CKDTree*> m_ObjectKdTreeMap;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H
|
||||
@@ -1,89 +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 "EditTool.h"
|
||||
|
||||
// Editor
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Class description.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CEditTool_ClassDesc
|
||||
: public CRefCountClassDesc
|
||||
{
|
||||
virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; }
|
||||
virtual REFGUID ClassID()
|
||||
{
|
||||
// {0A43AB8E-B1AE-44aa-93B1-229F73D58CA4}
|
||||
static const GUID guid = {
|
||||
0xa43ab8e, 0xb1ae, 0x44aa, { 0x93, 0xb1, 0x22, 0x9f, 0x73, 0xd5, 0x8c, 0xa4 }
|
||||
};
|
||||
return guid;
|
||||
}
|
||||
virtual QString ClassName() { return "EditTool.Default"; };
|
||||
virtual QString Category() { return "EditTool"; };
|
||||
};
|
||||
CEditTool_ClassDesc g_stdClassDesc;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEditTool::CEditTool(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_pClassDesc = &g_stdClassDesc;
|
||||
m_nRefCount = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEditTool::SetParentTool(CEditTool* pTool)
|
||||
{
|
||||
m_pParentTool = pTool;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEditTool* CEditTool::GetParentTool()
|
||||
{
|
||||
return m_pParentTool;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEditTool::Abort()
|
||||
{
|
||||
if (m_pParentTool)
|
||||
{
|
||||
GetIEditor()->SetEditTool(m_pParentTool);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->SetEditTool(0);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEditTool::GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects)
|
||||
{
|
||||
CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
|
||||
if (pSelection == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
|
||||
{
|
||||
outAffectedObjects.push_back(pSelection->GetObject(i));
|
||||
}
|
||||
}
|
||||
|
||||
#include <moc_EditTool.cpp>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user