Merge branch 'main' into Prefab/CreatePrefab

This commit is contained in:
srikappa
2021-04-22 14:54:01 -07:00
710 changed files with 29481 additions and 30600 deletions
@@ -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")
@@ -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")
@@ -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)
@@ -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")
@@ -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")
@@ -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)
@@ -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")
@@ -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)
@@ -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)
@@ -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)
@@ -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")
@@ -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)
@@ -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")
@@ -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")
@@ -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")
@@ -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")
@@ -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")
@@ -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
View File
@@ -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)
+1 -352
View File
@@ -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>
////////////////////////////////////////////////////////////////////////////////////////////////////
+1
View File
@@ -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;
+9 -2
View File
@@ -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;
}
+29 -2
View File
@@ -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;
}
}
+12 -2
View File
@@ -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)->
+3 -4
View File
@@ -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;
@@ -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
+2 -2
View File
@@ -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)
@@ -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)
@@ -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,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(); }
@@ -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;
}
@@ -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);
}
@@ -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
@@ -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
{
}
@@ -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;
@@ -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)
{
@@ -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;
@@ -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:
@@ -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);
@@ -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;
+2 -1
View File
@@ -28,8 +28,9 @@ ly_add_target(
${pal_dir}
BUILD_DEPENDENCIES
PRIVATE
3rdParty::OpenSSL
AZ::AzCore
PUBLIC
3rdParty::OpenSSL
)
ly_add_source_properties(
-6
View File
@@ -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();
}
-142
View File
@@ -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;
};
-40
View File
@@ -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>
-126
View File
@@ -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
-171
View File
@@ -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>
-60
View File
@@ -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);
-226
View File
@@ -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);
-15
View File
@@ -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);
-1
View File
@@ -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);
//////////////////////////////////////////////////////////////////////////
-1
View File
@@ -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
-134
View File
@@ -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
-89
View File
@@ -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