Merge branch 'main' into hultonha_LYN-2772_whitebox-atom

This commit is contained in:
hultonha
2021-04-22 15:40:48 +01:00
614 changed files with 29024 additions and 30167 deletions
@@ -0,0 +1,10 @@
"""
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.
"""
@@ -0,0 +1,13 @@
"""
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.
"""
import sys, os
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../PythonTests')
from PythonAssetBuilder import bootstrap_tests
@@ -134,11 +134,30 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
)
endif()
## Python Asset Builder ##
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::PythonAssetBuilder
TEST_SUITE periodic
TEST_SERIAL
PATH ${CMAKE_CURRENT_LIST_DIR}/PythonAssetBuilder
TIMEOUT 3600
RUNTIME_DEPENDENCIES
Legacy::Editor
Legacy::CryRenderNULL
AZ::AssetProcessor
AutomatedTesting.Assets
Gem::EditorPythonBindings.Editor
Gem::PythonAssetBuilder.Editor
COMPONENT TestTools
)
endif()
## Blast ##
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
@@ -0,0 +1,57 @@
"""
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.
"""
#
# This launches the AssetProcessor and Editor then attempts to find the expected
# assets created by a Python Asset Builder and the output of a scene pipeline script
#
import sys
import os
import pytest
import logging
pytest.importorskip('ly_test_tools')
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.parametrize('launcher_platform', ['windows_editor'])
@pytest.mark.parametrize('project', ['AutomatedTesting'])
@pytest.mark.parametrize('level', ['auto_test'])
class TestPythonAssetProcessing(object):
def test_DetectPythonCreatedAsset(self, request, editor, level, launcher_platform):
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'
]
timeout = 180
halt_on_unexpected = False
test_directory = os.path.join(os.path.dirname(__file__))
testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py')
editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile])
with editor.start():
editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log')
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(editor, editorlog_file)
waiter.wait_for(
lambda: editor.is_alive(),
timeout,
exc=("Log file '{}' was never opened by another process.".format(editorlog_file)),
interval=1)
log_monitor.monitor_log_for_lines(expected_lines, unexpected_lines, halt_on_unexpected, timeout)
@@ -0,0 +1,52 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import azlmbr.bus
import azlmbr.asset
import azlmbr.editor
import azlmbr.math
import azlmbr.legacy.general
def raise_and_stop(msg):
print (msg)
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
# These tests are meant to check that the test_asset.mock source asset turned into
# a test_asset.mock_asset product asset via the Python asset builder system
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset'
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False)
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}!')
print ('Mock asset exists')
# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets
def test_azmodel_product(generatedModelAssetPath, expectedSubId):
azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0)
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False)
assetIdString = assetId.to_string()
if (assetIdString.endswith(':' + expectedSubId) is False):
raise_and_stop(f'Asset has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath})!')
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')
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
@@ -0,0 +1,10 @@
"""
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.
"""
@@ -0,0 +1,17 @@
"""
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.
"""
import os
import sys
try:
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
import mock_asset_builder
except:
print ('skipping asset builder testing via mock_asset_builder')
@@ -0,0 +1,88 @@
"""
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.
"""
import uuid, os
import azlmbr.scene as sceneApi
import azlmbr.scene.graph
from scene_api import scene_data as sceneData
def get_mesh_node_names(sceneGraph):
meshDataList = []
node = sceneGraph.get_root()
children = []
while node.IsValid():
# store children to process after siblings
if sceneGraph.has_node_child(node):
children.append(sceneGraph.get_node_child(node))
# store any node that has mesh data content
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)))
# advance to next node
if sceneGraph.has_node_sibling(node):
node = sceneGraph.get_node_sibling(node)
elif children:
node = children.pop()
else:
node = azlmbr.scene.graph.NodeIndex()
return meshDataList
def update_manifest(scene):
graph = sceneData.SceneGraph(scene.graph)
meshNameList = get_mesh_node_names(graph)
sceneManifest = sceneData.SceneManifest()
sourceFilenameOnly = os.path.basename(scene.sourceFilename)
sourceFilenameOnly = sourceFilenameOnly.replace('.','_')
for activeMeshIndex in range(len(meshNameList)):
chunkName = meshNameList[activeMeshIndex]
chunkPath = chunkName.get_path()
meshGroupName = '{}_{}'.format(sourceFilenameOnly, chunkName.get_name())
meshGroup = sceneManifest.add_mesh_group(meshGroupName)
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)
return sceneManifest.export()
mySceneJobHandler = None
def on_update_manifest(args):
scene = args[0]
result = update_manifest(scene)
global mySceneJobHandler
mySceneJobHandler.disconnect()
mySceneJobHandler = None
return result
def main():
global mySceneJobHandler
mySceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler()
mySceneJobHandler.connect()
mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest)
if __name__ == "__main__":
main()
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:66d38948309ef273adf74b63eaa38f8fc2e2bdfbab3933d2ee082ce6a8cb108e
size 30496
@@ -0,0 +1,9 @@
{
"values":
[
{
"$type": "ScriptProcessorRule",
"scriptFilename": "Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py"
}
]
}
@@ -0,0 +1,121 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import azlmbr.asset
import azlmbr.asset.builder
import azlmbr.bus
import azlmbr.math
import os, traceback, binascii, sys
jobKeyName = 'Mock Asset'
def log_exception_traceback():
exc_type, exc_value, exc_tb = sys.exc_info()
data = traceback.format_exception(exc_type, exc_value, exc_tb)
print(str(data))
# creates a single job to compile for each platform
def create_jobs(request):
# create job descriptor for each platform
jobDescriptorList = []
for platformInfo in request.enabledPlatforms:
jobDesc = azlmbr.asset.builder.JobDescriptor()
jobDesc.jobKey = jobKeyName
jobDesc.set_platform_identifier(platformInfo.identifier)
jobDescriptorList.append(jobDesc)
response = azlmbr.asset.builder.CreateJobsResponse()
response.result = azlmbr.asset.builder.CreateJobsResponse_ResultSuccess
response.createJobOutputs = jobDescriptorList
return response
def on_create_jobs(args):
try:
request = args[0]
return create_jobs(request)
except:
log_exception_traceback()
# returing back a default CreateJobsResponse() records an asset error
return azlmbr.asset.builder.CreateJobsResponse()
def process_file(request):
# prepare output folder
basePath, _ = os.path.split(request.sourceFile)
outputPath = os.path.join(request.tempDirPath, basePath)
os.makedirs(outputPath, exist_ok=True)
# write out a mock file
basePath, sourceFile = os.path.split(request.sourceFile)
mockFilename = os.path.splitext(sourceFile)[0] + '.mock_asset'
mockFilename = os.path.join(basePath, mockFilename)
mockFilename = mockFilename.replace('\\', '/')
tempFilename = os.path.join(request.tempDirPath, mockFilename)
# write out a tempFilename like a JSON
fileOutput = open(tempFilename, "w")
fileOutput.write('{}')
fileOutput.close()
# generate a product asset file entry
subId = binascii.crc32(mockFilename.encode())
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
product = azlmbr.asset.builder.JobProduct(mockFilename, mockAssetType, subId)
product.dependenciesHandled = True
productOutputs = []
productOutputs.append(product)
# fill out response object
response = azlmbr.asset.builder.ProcessJobResponse()
response.outputProducts = productOutputs
response.resultCode = azlmbr.asset.builder.ProcessJobResponse_Success
response.dependenciesHandled = True
return response
# using the incoming 'request' find the type of job via 'jobKey' to determine what to do
def on_process_job(args):
try:
request = args[0]
if (request.jobDescription.jobKey.startswith(jobKeyName)):
return process_file(request)
except:
log_exception_traceback()
# returning back an empty ProcessJobResponse() will record an error
return azlmbr.asset.builder.ProcessJobResponse()
# register asset builder
def register_asset_builder(busId):
assetPattern = azlmbr.asset.builder.AssetBuilderPattern()
assetPattern.pattern = '*.mock'
assetPattern.type = azlmbr.asset.builder.AssetBuilderPattern_Wildcard
builderDescriptor = azlmbr.asset.builder.AssetBuilderDesc()
builderDescriptor.name = "Mock Builder"
builderDescriptor.patterns = [assetPattern]
builderDescriptor.busId = busId
builderDescriptor.version = 1
outcome = azlmbr.asset.builder.PythonAssetBuilderRequestBus(azlmbr.bus.Broadcast, 'RegisterAssetBuilder', builderDescriptor)
if outcome.IsSuccess():
# created the asset builder to hook into the notification bus
handler = azlmbr.asset.builder.PythonBuilderNotificationBusHandler()
handler.connect(busId)
handler.add_callback('OnCreateJobsRequest', on_create_jobs)
handler.add_callback('OnProcessJobRequest', on_process_job)
return handler
# create the asset builder handler
busIdString = '{CF5C74C1-9ED4-5851-95B1-0B15090DBEC7}'
busId = azlmbr.math.Uuid_CreateString(busIdString, 0)
handler = None
try:
handler = register_asset_builder(busId)
except:
handler = None
log_exception_traceback()
@@ -0,0 +1 @@
mock data
@@ -1,7 +1,6 @@
{
"configurations": [
{
"autoSelect": false,
"displayName": "Greenwich Park 02",
"skyboxImageAsset": {
"assetId": {
@@ -64,7 +63,6 @@
"shadowCatcherOpacity": 0.20000000298023225
},
{
"autoSelect": false,
"displayName": "Greenwich Park 02 (Alt)",
"skyboxImageAsset": {
"assetId": {
+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>
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -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.
@@ -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)->
@@ -506,6 +506,7 @@ namespace AZ::SettingsRegistryMergeUtils
void MergeSettingsToRegistry_AddRuntimeFilePaths(SettingsRegistryInterface& registry)
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
// Binary folder
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
@@ -514,28 +515,25 @@ namespace AZ::SettingsRegistryMergeUtils
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
constexpr size_t bufferSize = 64;
auto buffer = AZStd::fixed_string<bufferSize>::format("%s/project_path", BootstrapSettingsRootKey);
AZ::SettingsRegistryInterface::FixedValueString projectPathKey(buffer);
auto projectPathKey = FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
SettingsRegistryInterface::FixedValueString projectPathValue;
if (registry.Get(projectPathValue, projectPathKey))
{
// Cache folder
// Get the name of the asset platform assigned by the bootstrap. First check for platform version such as "windows_assets"
// and if that's missing just get "assets".
constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER;
buffer = AZStd::fixed_string<bufferSize>::format("%s/%s_assets", BootstrapSettingsRootKey, platformName);
AZStd::string_view assetPlatformKey(buffer);
// Use the platform codename to retrieve the default asset platform value
SettingsRegistryInterface::FixedValueString assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
if (!registry.Get(assetPlatform, assetPlatformKey))
FixedValueString assetPlatform;
if (auto assetPlatformKey = FixedValueString::format("%s/%s_assets", BootstrapSettingsRootKey, AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER);
!registry.Get(assetPlatform, assetPlatformKey))
{
buffer = AZStd::fixed_string<bufferSize>::format("%s/assets", BootstrapSettingsRootKey);
assetPlatformKey = AZStd::string_view(buffer);
assetPlatformKey = FixedValueString::format("%s/assets", BootstrapSettingsRootKey);
registry.Get(assetPlatform, assetPlatformKey);
}
if (assetPlatform.empty())
{
// Use the platform codename to retrieve the default asset platform value
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
}
// Project path - corresponds to the @devassets@ alias
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
@@ -575,8 +573,7 @@ namespace AZ::SettingsRegistryMergeUtils
{
// Cache: project root - no corresponding fileIO alias, but this is where the asset database lives.
// A registry override is accepted using the "project_cache_path" key.
buffer = AZStd::fixed_string<bufferSize>::format("%s/project_cache_path", BootstrapSettingsRootKey);
AZStd::string_view projectCacheRootOverrideKey(buffer);
auto projectCacheRootOverrideKey = FixedValueString::format("%s/project_cache_path", BootstrapSettingsRootKey);
// Clear path to make sure that the `project_cache_path` value isn't concatenated to the project path
path.clear();
if (registry.Get(path.Native(), projectCacheRootOverrideKey))
+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(
@@ -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)
@@ -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);
}
@@ -136,6 +136,48 @@ namespace AzToolsFramework
return entity->GetName();
}
EntityList EntityIdListToEntityList(const EntityIdList& inputEntityIds)
{
EntityList entities;
entities.reserve(inputEntityIds.size());
for (AZ::EntityId entityId : inputEntityIds)
{
if (!entityId.IsValid())
{
continue;
}
if (auto entity = GetEntityById(entityId))
{
entities.emplace_back(entity);
}
}
return entities;
}
EntityList EntityIdSetToEntityList(const EntityIdSet& inputEntityIds)
{
EntityList entities;
entities.reserve(inputEntityIds.size());
for (AZ::EntityId entityId : inputEntityIds)
{
if (!entityId.IsValid())
{
continue;
}
if (auto entity = GetEntityById(entityId))
{
entities.emplace_back(entity);
}
}
return entities;
}
void GetAllComponentsForEntity(const AZ::Entity* entity, AZ::Entity::ComponentArrayType& componentsOnEntity)
{
if (entity)
@@ -1068,6 +1110,45 @@ namespace AzToolsFramework
return !allEntityClonesContainer.m_entities.empty();
}
EntityIdSet GetCulledEntityHierarchy(const EntityIdList& entities)
{
EntityIdSet culledEntities;
for (const AZ::EntityId& entityId : entities)
{
bool selectionIncludesTransformHeritage = false;
AZ::EntityId parentEntityId = entityId;
do
{
AZ::EntityId nextParentId;
AZ::TransformBus::EventResult(
/*result*/ nextParentId,
/*address*/ parentEntityId,
&AZ::TransformBus::Events::GetParentId);
parentEntityId = nextParentId;
if (!parentEntityId.IsValid())
{
break;
}
for (const AZ::EntityId& parentCheck : entities)
{
if (parentCheck == parentEntityId)
{
selectionIncludesTransformHeritage = true;
break;
}
}
} while (parentEntityId.IsValid() && !selectionIncludesTransformHeritage);
if (!selectionIncludesTransformHeritage)
{
culledEntities.insert(entityId);
}
}
return culledEntities;
}
namespace Internal
{
void CloneSliceEntitiesAndChildren(
@@ -47,6 +47,9 @@ namespace AzToolsFramework
AZStd::string GetEntityName(const AZ::EntityId& entityId, const AZStd::string_view& nameOverride = {});
EntityList EntityIdListToEntityList(const EntityIdList& inputEntityIds);
EntityList EntityIdSetToEntityList(const EntityIdSet& inputEntityIds);
template <typename... ComponentTypes>
struct AddComponents
{
@@ -202,4 +205,8 @@ namespace AzToolsFramework
/// Wrap EBus SetSelectedEntities call.
void SelectEntities(const AzToolsFramework::EntityIdList& entities);
/// Return a set of entities, culling any that have an ancestor in the list.
/// e.g. This is useful for getting a concise set of entities that need to be duplicated.
EntityIdSet GetCulledEntityHierarchy(const EntityIdList& entities);
}; // namespace AzToolsFramework
@@ -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;
@@ -279,18 +281,29 @@ namespace AzToolsFramework
AZStd::unique_ptr<Prefab::Instance> createdPrefabInstance =
m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath);
if (!instanceToParentUnder)
{
instanceToParentUnder = *m_rootInstance;
}
if (createdPrefabInstance)
{
if (!instanceToParentUnder)
{
instanceToParentUnder = *m_rootInstance;
}
Prefab::Instance& addedInstance = instanceToParentUnder->get().AddInstance(AZStd::move(createdPrefabInstance));
HandleEntitiesAdded({addedInstance.m_containerEntity.get()});
AZ::Entity* containerEntity = addedInstance.m_containerEntity.get();
containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({containerEntity});
HandleEntitiesAdded(entities);
// Update the template of the instance since we modified the entities of the instance by calling HandleEntitiesAdded.
Prefab::PrefabDom serializedInstance;
if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance))
{
m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance);
}
return addedInstance;
}
HandleEntitiesAdded(entities);
return AZStd::nullopt;
}
@@ -186,7 +186,7 @@ namespace AzToolsFramework
PlayInEditorData m_playInEditorData;
//////////////////////////////////////////////////////////////////////////
// PrefabSystemComponentInterface interface implementation
// PrefabEditorEntityOwnershipInterface implementation
Prefab::InstanceOptionalReference CreatePrefab(
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Prefab::Instance>>&& nestedPrefabInstances,
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
@@ -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)
@@ -563,7 +567,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);
@@ -15,6 +15,7 @@
#include <AzCore/Component/TickBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/TemplateInstanceMapperInterface.h>
@@ -116,10 +117,24 @@ namespace AzToolsFramework
"Could not find Template using Id '%llu'. Unable to update Instance.",
currentTemplateId);
// Remove the instance from update queue if its corresponding template couldn't be found
isUpdateSuccessful = false;
m_instancesUpdateQueue.pop();
continue;
}
}
auto findInstancesResult = m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId)->get();
if (findInstancesResult.find(instanceToUpdate) == findInstancesResult.end())
{
// Since nested instances get reconstructed during propagation, remove any nested instance that no longer
// maps to a template.
isUpdateSuccessful = false;
m_instancesUpdateQueue.pop();
continue;
}
Template& currentTemplate = currentTemplateReference->get();
Instance::EntityList newEntities;
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, currentTemplate.GetPrefabDom()))
@@ -139,9 +154,18 @@ namespace AzToolsFramework
}
m_instancesUpdateQueue.pop();
}
for (auto entityIdIterator = selectedEntityIds.begin(); entityIdIterator != selectedEntityIds.end(); entityIdIterator++)
{
// Since entities get recreated during propagation, we need to check whether the entities correspoding to the list
// of selected entity ids are present or not.
AZ::Entity* entity = GetEntityById(*entityIdIterator);
if (entity == nullptr)
{
selectedEntityIds.erase(entityIdIterator--);
}
}
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
// Enable the Outliner
@@ -15,15 +15,16 @@
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Utils/TypeHash.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityIdMapper.h>
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/Instance/InstanceToTemplateInterface.h>
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
#include <AzToolsFramework/Prefab/PrefabUndo.h>
@@ -37,12 +38,14 @@ namespace AzToolsFramework
void PrefabPublicHandler::RegisterPrefabPublicHandlerInterface()
{
m_instanceEntityMapperInterface = AZ::Interface<InstanceEntityMapperInterface>::Get();
AZ_Assert(
m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface");
AZ_Assert(m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface");
m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get();
AZ_Assert(m_instanceToTemplateInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceToTemplateInterface");
m_prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
AZ_Assert(m_prefabLoaderInterface, "Could not get PrefabLoaderInterface on PrefabPublicHandler construction.");
m_prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
AZ_Assert(m_prefabSystemComponentInterface, "Could not get PrefabSystemComponentInterface on PrefabPublicHandler construction.");
@@ -59,92 +62,160 @@ namespace AzToolsFramework
}
PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector<AZ::EntityId>& entityIds, AZ::IO::PathView filePath)
{
EntityList inputEntityList, topLevelEntities;
AZ::EntityId commonRootEntityId;
InstanceOptionalReference commonRootEntityOwningInstance;
PrefabOperationResult findCommonRootOutcome = FindCommonRootOwningInstance(
entityIds, inputEntityList, topLevelEntities, commonRootEntityId, commonRootEntityOwningInstance);
if (!findCommonRootOutcome.IsSuccess())
{
return findCommonRootOutcome;
}
InstanceOptionalReference instanceToCreate;
{
// Initialize Undo Batch object
ScopedUndoBatch undoBatch("Create Prefab");
PrefabDom commonRootInstanceDomBeforeCreate;
m_instanceToTemplateInterface->GenerateDomForInstance(
commonRootInstanceDomBeforeCreate, commonRootEntityOwningInstance->get());
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
{
return AZ::Failure(
AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
}
// When we create a prefab with other prefab instances, we have to remove the existing links between the source and
// target templates of the other instances.
for (auto& nestedInstance : instances)
{
PrefabUndoHelpers::RemoveLink(
nestedInstance->GetTemplateId(), commonRootEntityOwningInstance->get().GetTemplateId(),
nestedInstance->GetInstanceAlias(), nestedInstance->GetLinkId(), undoBatch.GetUndoBatch());
}
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(PrefabEditorEntityOwnershipInterface unavailable)."));
}
// Create the Prefab
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
if (!instanceToCreate)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(A null instance is returned)."));
}
PrefabUndoHelpers::UpdatePrefabInstance(
commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch());
CreateLink(
topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(),
commonRootEntityId);
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
// Change top level entities to be parented to the container entity
// Mark them as dirty so this change is correctly applied to the template
for (AZ::Entity* topLevelEntity : topLevelEntities)
{
m_prefabUndoCache.UpdateCache(topLevelEntity->GetId());
undoBatch.MarkEntityDirty(topLevelEntity->GetId());
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
}
// Select Container Entity
{
auto selectionUndo = aznew SelectionCommand({containerEntityId}, "Select Prefab Container Entity");
selectionUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
}
}
// Save Template to file
m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
return AZ::Success();
}
PrefabOperationResult PrefabPublicHandler::FindCommonRootOwningInstance(
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance)
{
// Retrieve entityList from entityIds
EntityList inputEntityList;
EntityIdListToEntityList(entityIds, inputEntityList);
inputEntityList = EntityIdListToEntityList(entityIds);
// Find common root and top level entities
bool entitiesHaveCommonRoot = false;
AZ::EntityId commonRootEntityId;
EntityList topLevelEntities;
AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
entitiesHaveCommonRoot,
&AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive,
inputEntityList,
commonRootEntityId,
&topLevelEntities
);
entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList,
commonRootEntityId, &topLevelEntities);
// Bail if entities don't share a common root
if (!entitiesHaveCommonRoot)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
}
AZ::Entity* commonRootEntity = nullptr;
if (commonRootEntityId.IsValid())
{
commonRootEntity = GetEntityById(commonRootEntityId);
return AZ::Failure(AZStd::string("Failed to create a prefab: Provided entities do not share a common root."));
}
// Retrieve the owning instance of the common root entity, which will be our new instance's parent instance.
InstanceOptionalReference commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId);
AZ_Assert(commonRootEntityOwningInstance.has_value(), "Failed to create prefab : "
"Couldn't get a valid owning instance for the common root entity of the enities provided");
AZStd::vector<AZ::Entity*> entities;
AZStd::vector<AZStd::unique_ptr<Instance>> instances;
// Retrieve all entities affected and identify Instances
if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances))
commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId);
if (!commonRootEntityOwningInstance)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root."));
AZ_Assert(
false,
"Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided");
return AZ::Failure(AZStd::string(
"Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided"));
}
return AZ::Success();
}
auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get();
if (!prefabEditorEntityOwnershipInterface)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(PrefabEditorEntityOwnershipInterface unavailable)."));
}
void PrefabPublicHandler::CreateLink(
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId)
{
AZ::EntityId containerEntityId = sourceInstance.GetContainerEntityId();
AZ::Entity* containerEntity = GetEntityById(containerEntityId);
Prefab::PrefabDom containerEntityDomBefore;
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity);
InstanceOptionalReference instance = prefabEditorEntityOwnershipInterface->CreatePrefab(
entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance);
if (!instance)
{
return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error "
"(A null instance is returned)."));
}
AZ::EntityId containerEntityId = instance->get().GetContainerEntityId();
AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero());
AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero());
// Set the transform (translation, rotation) of the container entity
GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation);
// Set container entity to be child of common root
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation);
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation);
// Set container entity to be child of common root
AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId);
// Assign the EditorPrefabComponent to the instance container
EntityCompositionRequests::AddComponentsOutcome outcome;
EntityCompositionRequestBus::BroadcastResult(
outcome, &EntityCompositionRequests::AddComponentsToEntities, EntityIdList{containerEntityId},
AZ::ComponentTypeList{azrtti_typeid<AzToolsFramework::Prefab::EditorPrefabComponent>()});
// Change top level entities to be parented to the container entity
for (AZ::Entity* topLevelEntity : topLevelEntities)
{
AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId);
}
return AZ::Success();
PrefabDom containerEntityDomAfter;
m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity);
PrefabDom patch;
m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId);
PrefabUndoHelpers::CreateLink(
sourceInstance.GetTemplateId(), targetTemplateId, patch, sourceInstance.GetInstanceAlias(),
undoBatch);
// Update the cache - this prevents these changes from being stored in the regular undo/redo nodes
m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter));
}
PrefabOperationResult PrefabPublicHandler::InstantiatePrefab(AZStd::string_view /*filePath*/, AZ::EntityId /*parent*/, AZ::Vector3 /*position*/)
@@ -174,14 +245,7 @@ namespace AzToolsFramework
AZStd::string("SavePrefab - Path error. Path could be invalid, or the prefab may not be loaded in this level."));
}
auto prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
if (prefabLoaderInterface == nullptr)
{
return AZ::Failure(AZStd::string(
"Could not save prefab - internal error (PrefabLoaderInterface unavailable)."));
}
if (!prefabLoaderInterface->SaveTemplate(templateId))
if (!m_prefabLoaderInterface->SaveTemplate(templateId))
{
return AZ::Failure(AZStd::string("Could not save prefab - internal error (Json write operation failure)."));
}
@@ -262,13 +326,13 @@ namespace AzToolsFramework
if (instanceOptionalReference.has_value())
{
PrefabDom beforeState;
m_prefabUndoCache.Retrieve(entityId, beforeState);
PrefabDom afterState;
AZ::Entity* entity = GetEntityById(entityId);
if (entity)
{
PrefabDom beforeState;
m_prefabUndoCache.Retrieve(entityId, beforeState);
m_instanceToTemplateInterface->GenerateDomForEntity(afterState, *entity);
PrefabDom patch;
@@ -287,7 +351,10 @@ namespace AzToolsFramework
// Update the cache
m_prefabUndoCache.Store(entityId, AZStd::move(afterState));
}
else
{
m_prefabUndoCache.PurgeCache(entityId);
}
}
}
@@ -419,8 +486,7 @@ namespace AzToolsFramework
InstanceOptionalReference instance = GetOwnerInstanceByEntityId(entityIds[0]);
// Retrieve entityList from entityIds
EntityList inputEntityList;
EntityIdListToEntityList(entityIds, inputEntityList);
EntityList inputEntityList = EntityIdListToEntityList(entityIds);
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
@@ -655,7 +721,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());
@@ -739,7 +805,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;
@@ -767,18 +833,5 @@ namespace AzToolsFramework
return true;
}
void PrefabPublicHandler::EntityIdListToEntityList(const EntityIdList& inputEntityIds, EntityList& outEntities)
{
outEntities.reserve(inputEntityIds.size());
for (AZ::EntityId entityId : inputEntityIds)
{
if (entityId.IsValid())
{
outEntities.emplace_back(GetEntityById(entityId));
}
}
}
}
}
@@ -27,8 +27,10 @@ namespace AzToolsFramework
namespace Prefab
{
class Instance;
class InstanceEntityMapperInterface;
class InstanceToTemplateInterface;
class PrefabLoaderInterface;
class PrefabSystemComponentInterface;
class PrefabPublicHandler final
@@ -67,13 +69,40 @@ namespace AzToolsFramework
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
/**
* Creates a link between the templates of an instance and its parent.
*
* \param topLevelEntities The list of entities that are immediate children to the container entity of the instance.
* \param sourceInstance The instance that corresponds to the source template of the link.
* \param targetInstance The id of the target template.
* \param undoBatch The undo batch to set as parent for this create link action.
* \param commonRootEntityId The id of the entity that the source instance should be parented under.
*/
void CreateLink(
const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId,
UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId);
/**
* Given a list of entityIds, finds the prefab instance that owns the common root entity of the entityIds.
*
* \param entityIds The list of entity ids.
* \param inputEntityList The list of entities corresponding to the entity ids.
* \param topLevelEntities The list of entities that are immediate children of the common root entity.
* \param commonRootEntityId The entity id of the common root entity of all the entityIds.
* \param commonRootEntityOwningInstance The owning instance of the common root entity.
* \return PrefabOperationResult indicating whether the action was successful or not.
*/
PrefabOperationResult FindCommonRootOwningInstance(
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance);
static Instance* GetParentInstance(Instance* instance);
static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant);
static void GenerateContainerEntityTransform(const EntityList& topLevelEntities, AZ::Vector3& translation, AZ::Quaternion& rotation);
static void EntityIdListToEntityList(const EntityIdList& inputEntityIds, EntityList& outEntities);
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
PrefabLoaderInterface* m_prefabLoaderInterface = nullptr;
PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr;
// Caches entity states for undo/redo purposes
@@ -104,7 +104,6 @@ namespace AzToolsFramework
return nullptr;
}
AZStd::unique_ptr<Instance> newInstance = AZStd::make_unique<Instance>(AZStd::move(containerEntity));
for (AZ::Entity* entity : entities)
@@ -122,6 +121,7 @@ namespace AzToolsFramework
}
newInstance->SetTemplateSourcePath(relativeFilePath);
newInstance->SetContainerEntityName(relativeFilePath.Stem().Native());
TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance);
if (newTemplateId == InvalidTemplateId)
@@ -142,7 +142,6 @@ namespace AzToolsFramework
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId)
{
UpdatePrefabInstances(templateId);
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
{
@@ -153,15 +152,24 @@ namespace AzToolsFramework
templateIdToLinkIdsIterator->second.end()));
UpdateLinkedInstances(linkIdsToUpdateQueue);
}
else
{
UpdatePrefabInstances(templateId);
}
}
void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom)
{
PrefabDom& templateDomToUpdate = FindTemplateDom(templateId);
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
auto templateToUpdate = FindTemplate(templateId);
if (templateToUpdate)
{
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
PropagateTemplateChanges(templateId);
PrefabDom& templateDomToUpdate = templateToUpdate->get().GetPrefabDom();
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
{
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
templateToUpdate->get().MarkAsDirty(true);
PropagateTemplateChanges(templateId);
}
}
}
@@ -615,7 +623,12 @@ namespace AzToolsFramework
instancesValue = memberFound->value;
}
instancesValue->get().AddMember(rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator());
// Only add the instance if it's not there already
if (instancesValue->get().FindMember(rapidjson::StringRef(instanceAlias.c_str())) == instancesValue->get().MemberEnd())
{
instancesValue->get().AddMember(
rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator());
}
Template& sourceTemplate = sourceTemplateRef->get();
@@ -124,7 +124,7 @@ namespace AzToolsFramework
const TemplateId& targetId,
const TemplateId& sourceId,
const InstanceAlias& instanceAlias,
const PrefabDomReference linkDom,
PrefabDomReference linkDom,
const LinkId linkId)
{
m_targetId = targetId;
@@ -101,7 +101,7 @@ namespace AzToolsFramework
const TemplateId& targetId,
const TemplateId& sourceId,
const InstanceAlias& instanceAlias,
const PrefabDomReference linkDom = PrefabDomReference(),
PrefabDomReference linkDom = PrefabDomReference(),
const LinkId linkId = InvalidLinkId);
void Undo() override;
@@ -32,6 +32,28 @@ namespace AzToolsFramework
state->SetParent(undoBatch);
state->Redo();
}
void CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch)
{
auto linkAddUndo = aznew PrefabUndoInstanceLink("Create Link");
linkAddUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, patch, InvalidLinkId);
linkAddUndo->SetParent(undoBatch);
linkAddUndo->Redo();
}
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias,
LinkId linkId, UndoSystem::URSequencePoint* undoBatch)
{
auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Remove Link");
PrefabDom emptyLinkDom;
linkRemoveUndo->Capture(
targetTemplateId, sourceTemplateId, instanceAlias, emptyLinkDom, linkId);
linkRemoveUndo->SetParent(undoBatch);
linkRemoveUndo->Redo();
}
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -21,6 +21,12 @@ namespace AzToolsFramework
void UpdatePrefabInstance(
const Instance& instance, AZStd::string_view undoMessage, const PrefabDom& instanceDomBeforeUpdate,
UndoSystem::URSequencePoint* undoBatch);
void CreateLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch,
const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch);
void RemoveLink(
TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias,
LinkId linkId, UndoSystem::URSequencePoint* undoBatch);
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -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;
@@ -0,0 +1,57 @@
/*
* 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 <AzTest/AzTest.h>
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
namespace UnitTest
{
class EditorEntityHelpersTest
: public ToolsApplicationFixture
{
void SetUpEditorFixtureImpl() override
{
m_parent1 = CreateDefaultEditorEntity("Parent1");
m_child1 = CreateDefaultEditorEntity("Child1");
m_child2 = CreateDefaultEditorEntity("Child2");
m_grandChild1 = CreateDefaultEditorEntity("GrandChild1");
m_parent2 = CreateDefaultEditorEntity("Parent2");
AZ::TransformBus::Event(m_child1, &AZ::TransformBus::Events::SetParent, m_parent1);
AZ::TransformBus::Event(m_child2, &AZ::TransformBus::Events::SetParent, m_parent1);
AZ::TransformBus::Event(m_grandChild1, &AZ::TransformBus::Events::SetParent, m_child1);
}
public:
AZ::EntityId m_parent1;
AZ::EntityId m_child1;
AZ::EntityId m_child2;
AZ::EntityId m_grandChild1;
AZ::EntityId m_parent2;
};
TEST_F(EditorEntityHelpersTest, EditorEntityHelpersTests_GetCulledEntityHierarchy)
{
AzToolsFramework::EntityIdList testEntityIds{ m_parent1, m_child1, m_child2, m_grandChild1, m_parent2 };
AzToolsFramework::EntityIdSet culledSet = AzToolsFramework::GetCulledEntityHierarchy(testEntityIds);
// There should only be two EntityIds returned (m_parent1, and m_parent2),
// since all the others should be culled out since they have a common ancestor
// in the list already
using ::testing::UnorderedElementsAre;
EXPECT_THAT(culledSet, UnorderedElementsAre(m_parent1, m_parent2));
}
}
@@ -85,7 +85,9 @@ set(FILES
Prefab/SpawnableSortEntitiesTestFixture.cpp
Prefab/SpawnableSortEntitiesTestFixture.h
Entity/EditorEntityContextComponentTests.cpp
Entity/EditorEntityHelpersTests.cpp
Entity/EditorEntitySearchComponentTests.cpp
Entity/EditorEntitySelectionTests.cpp
SliceStabilityTests/SliceStabilityTestFramework.h
SliceStabilityTests/SliceStabilityTestFramework.cpp
SliceStabilityTests/SliceStabilityCreateTests.cpp
+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,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>
-175
View File
@@ -1,175 +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_EDITTOOL_H
#define CRYINCLUDE_EDITOR_EDITTOOL_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "QtViewPaneManager.h"
#endif
class CViewport;
struct IClassDesc;
struct ITransformManipulator;
struct HitContext;
enum EEditToolType
{
EDIT_TOOL_TYPE_PRIMARY,
EDIT_TOOL_TYPE_SECONDARY,
};
/*!
* CEditTool is an abstract base class for All Editing Tools supported by Editor.
* Edit tools handle specific editing modes in viewports.
*/
class SANDBOX_API CEditTool
: public QObject
{
Q_OBJECT
public:
explicit CEditTool(QObject* parent = nullptr);
//////////////////////////////////////////////////////////////////////////
// For reference counting.
//////////////////////////////////////////////////////////////////////////
void AddRef() { m_nRefCount++; };
void Release()
{
AZ_Assert(m_nRefCount > 0, "Negative ref count");
if (--m_nRefCount == 0)
{
DeleteThis();
}
};
//! Returns class description for this tool.
IClassDesc* GetClassDesc() const { return m_pClassDesc; }
virtual void SetParentTool(CEditTool* pTool);
virtual CEditTool* GetParentTool();
virtual EEditToolType GetType() { return EDIT_TOOL_TYPE_PRIMARY; }
virtual EOperationMode GetMode() { return eOperationModeNone; }
// Abort tool.
virtual void Abort();
// Accept tool.
virtual void Accept([[maybe_unused]] bool resetPosition = false) {}
//! Status text displayed when this tool is active.
void SetStatusText(const QString& text) { m_statusText = text; };
QString GetStatusText() { return m_statusText; };
// Description:
// Activates tool.
// Arguments:
// pPreviousTool - Previously active edit tool.
// Return:
// True if the tool can be activated,
virtual bool Activate([[maybe_unused]] CEditTool* pPreviousTool) { return true; };
//! Used to pass user defined data to edit tool from ToolButton.
virtual void SetUserData([[maybe_unused]] const char* key, [[maybe_unused]] void* userData) {};
//! Called when user starts using this tool.
//! Flags is comnination of ObjectEditFlags flags.
virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {};
//! Called when user ends using this tool.
virtual void EndEditParams() {};
// Called each frame to display tool for given viewport.
virtual void Display(struct DisplayContext& dc) = 0;
//! Mouse callback sent from viewport.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Return false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport that sent this callback.
//! @param event Indicate what kind of event occured in viewport.
//! @param point 2D coordinate in viewport where event occured.
//! @param flags Additional flags (MK_LBUTTON,etc..) or from (MouseEventFlags) specified by viewport when calling callback.
virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) = 0;
//! Called when key in viewport is pressed while using this tool.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Returns false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport where key was pressed.
//! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h
//! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key.
//! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN)
virtual bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; };
//! Called when key in viewport is released while using this tool.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Returns false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport where key was pressed.
//! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h
//! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key.
//! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN)
virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; };
//! Called when mouse is moved and give oportunity to tool to set it own cursor.
//! @return true if cursor changed. or false otherwise.
virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; };
// Return objects affected by this edit tool. The returned objects usually will be the selected objects.
virtual void GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects);
// Called in response to the dragging of the manipulator in the view.
// Allow edit tool to handle manipulator dragging the way it wants.
virtual void OnManipulatorDrag([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] QPoint& p0, [[maybe_unused]] QPoint& p1, [[maybe_unused]] const Vec3& value) {}
virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, const Vec3& value)
{
// Overload with less boiler-plate
QPoint p0, p1;
OnManipulatorDrag(view, pManipulator, p0, p1, value);
}
// Called in response to mouse event of the manipulator in the view
virtual void OnManipulatorMouseEvent([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags, [[maybe_unused]] bool bHitGizmo = false) {}
virtual bool IsNeedMoveTool() { return false; }
virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return false; }
virtual bool IsNeedToSkipPivotBoxForObjects() { return false; }
virtual bool IsDisplayGrid() { return true; }
virtual bool IsUpdateUIPanel() { return false; }
virtual bool IsMoveToObjectModeAfterEnd() { return true; }
virtual bool IsCircleTypeRotateGizmo() { return false; }
// Draws object specific helpers for this tool
virtual void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) {}
// Hit test against edit tool
virtual bool HitTest([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] HitContext& hc) { return false; }
protected:
virtual ~CEditTool() {};
//////////////////////////////////////////////////////////////////////////
// Delete edit tool.
//////////////////////////////////////////////////////////////////////////
virtual void DeleteThis() = 0;
protected:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
_smart_ptr<CEditTool> m_pParentTool; // Pointer to parent edit tool.
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
QString m_statusText;
IClassDesc* m_pClassDesc;
int m_nRefCount;
};
#endif // CRYINCLUDE_EDITOR_EDITTOOL_H
@@ -63,11 +63,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Field("DeepSelectionRange", &DeepSelection::m_deepSelectionRange)
->Field("StickDuplicate", &DeepSelection::m_stickDuplicate);
serialize.Class<VertexSnapping>()
->Version(1)
->Field("VertexCubeSize", &VertexSnapping::m_vertexCubeSize)
->Field("RenderPenetratedBoundBox", &VertexSnapping::m_bRenderPenetratedBoundBox);
serialize.Class<SliceSettings>()
->Version(1)
->Field("DynamicByDefault", &SliceSettings::m_slicesDynamicByDefault);
@@ -78,7 +73,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Field("Messaging", &CEditorPreferencesPage_General::m_messaging)
->Field("Undo", &CEditorPreferencesPage_General::m_undo)
->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection)
->Field("Vertex Snapping", &CEditorPreferencesPage_General::m_vertexSnapping)
->Field("Slice Settings", &CEditorPreferencesPage_General::m_sliceSettings);
@@ -119,12 +113,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Max, 1000.0f);
editContext->Class<VertexSnapping>("Vertex Snapping", "")
->DataElement(AZ::Edit::UIHandlers::SpinBox, &VertexSnapping::m_vertexCubeSize, "Vertex Cube Size", "Vertex Cube Size")
->Attribute(AZ::Edit::Attributes::Min, 0.0001f)
->Attribute(AZ::Edit::Attributes::Max, 1.0f)
->DataElement(AZ::Edit::UIHandlers::CheckBox, &VertexSnapping::m_bRenderPenetratedBoundBox, "Render Penetrated BoundBoxes", "Render Penetrated BoundBoxes");
editContext->Class<SliceSettings>("Slices", "")
->DataElement(AZ::Edit::UIHandlers::CheckBox, &SliceSettings::m_slicesDynamicByDefault, "New Slices Dynamic By Default", "When creating slices, they will be set to dynamic by default");
@@ -135,7 +123,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_vertexSnapping, "Vertex Snapping", "Vertex Snapping")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_sliceSettings, "Slices", "Slice Settings");
}
}
@@ -189,10 +176,6 @@ void CEditorPreferencesPage_General::OnApply()
gSettings.deepSelectionSettings.fRange = m_deepSelection.m_deepSelectionRange;
gSettings.deepSelectionSettings.bStickDuplicate = m_deepSelection.m_stickDuplicate;
//vertex snapping
gSettings.vertexSnappingSettings.vertexCubeSize = m_vertexSnapping.m_vertexCubeSize;
gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox = m_vertexSnapping.m_bRenderPenetratedBoundBox;
//slices
gSettings.sliceSettings.dynamicByDefault = m_sliceSettings.m_slicesDynamicByDefault;
@@ -236,10 +219,6 @@ void CEditorPreferencesPage_General::InitializeSettings()
m_deepSelection.m_deepSelectionRange = gSettings.deepSelectionSettings.fRange;
m_deepSelection.m_stickDuplicate = gSettings.deepSelectionSettings.bStickDuplicate;
//vertex snapping
m_vertexSnapping.m_vertexCubeSize = gSettings.vertexSnappingSettings.vertexCubeSize;
m_vertexSnapping.m_bRenderPenetratedBoundBox = gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox;
//slices
m_sliceSettings.m_slicesDynamicByDefault = gSettings.sliceSettings.dynamicByDefault;
}
@@ -88,14 +88,6 @@ private:
bool m_stickDuplicate;
};
struct VertexSnapping
{
AZ_TYPE_INFO(VertexSnapping, "{20F16350-990C-4096-86E3-40D56DDDD702}")
float m_vertexCubeSize;
bool m_bRenderPenetratedBoundBox;
};
struct SliceSettings
{
AZ_TYPE_INFO(SliceSettings, "{8505CCC1-874C-4389-B51A-B9E5FF70CFDA}")
@@ -107,7 +99,6 @@ private:
Messaging m_messaging;
Undo m_undo;
DeepSelection m_deepSelection;
VertexSnapping m_vertexSnapping;
SliceSettings m_sliceSettings;
QIcon m_icon;
};
+21 -9
View File
@@ -65,7 +65,6 @@
#include "Util/fastlib.h"
#include "CryEditDoc.h"
#include "GameEngine.h"
#include "EditTool.h"
#include "ViewManager.h"
#include "Objects/DisplayContext.h"
#include "DisplaySettings.h"
@@ -276,9 +275,6 @@ void EditorViewportWidget::paintEvent([[maybe_unused]] QPaintEvent* event)
if ((ge && ge->IsLevelLoaded()) || (GetType() != ET_ViewportCamera))
{
setRenderOverlayVisible(true);
m_isOnPaint = true;
Update();
m_isOnPaint = false;
}
else
{
@@ -682,6 +678,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
}
SetCurrentCursor(STD_CURSOR_GAME);
}
if (m_renderViewport)
{
m_renderViewport->GetControllerList()->SetEnabled(false);
}
}
break;
@@ -700,6 +701,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
RestoreViewportAfterGameMode();
}
if (m_renderViewport)
{
m_renderViewport->GetControllerList()->SetEnabled(true);
}
break;
case eNotify_OnCloseScene:
@@ -730,6 +736,8 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
// meters above the terrain (default terrain height is 32)
viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f));
SetViewTM(viewTM);
UpdateScene();
}
break;
@@ -809,6 +817,10 @@ void EditorViewportWidget::OnBeginPrepareRender()
return;
}
m_isOnPaint = true;
Update();
m_isOnPaint = false;
float fNearZ = GetIEditor()->GetConsoleVar("cl_DefaultNearPlane");
float fFarZ = m_Camera.GetFarPlane();
@@ -880,6 +892,11 @@ void EditorViewportWidget::OnBeginPrepareRender()
GetIEditor()->GetSystem()->SetViewCamera(m_Camera);
if (GetIEditor()->IsInGameMode())
{
return;
}
PreWidgetRendering();
RenderAll();
@@ -905,11 +922,6 @@ void EditorViewportWidget::OnBeginPrepareRender()
m_debugDisplay->DepthTestOn();
PostWidgetRendering();
if (!m_renderer->IsStereoEnabled())
{
GetIEditor()->GetSystem()->RenderStatistics();
}
}
//////////////////////////////////////////////////////////////////////////
-3
View File
@@ -125,9 +125,6 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE
{
QDir::setCurrent(pEditor->GetPrimaryCDFolder());
// Close all Editor tools
pEditor->SetEditTool(0);
QString sLevelPath = Path::AddSlash(pGameEngine->GetLevelPath());
if (subdirectory && subdirectory[0] && strcmp(subdirectory, ".") != 0)
{
-38
View File
@@ -40,7 +40,6 @@ struct QMetaObject;
class CBaseObject;
class CCryEditDoc;
class CSelectionGroup;
class CEditTool;
class CAnimationContext;
class CTrackViewSequenceManager;
class CGameEngine;
@@ -391,21 +390,6 @@ enum EModifiedModule
eModifiedAll = -1
};
//! Callback class passed to PickObject.
struct IPickObjectCallback
{
virtual ~IPickObjectCallback() = default;
//! Called when object picked.
virtual void OnPick(CBaseObject* picked) = 0;
//! Called when pick mode cancelled.
virtual void OnCancelPick() = 0;
//! Return true if specified object is pickable.
virtual bool OnPickFilter([[maybe_unused]] CBaseObject* filterObject) { return true; };
//! If need a specific behavior when holding space, return true or if not, return false.
virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return false; }
};
//! Class provided by editor for various registration functions.
struct CRegistrationContext
{
@@ -570,20 +554,6 @@ struct IEditor
//! Get access to object manager.
virtual struct IObjectManager* GetObjectManager() = 0;
virtual CSettingsManager* GetSettingsManager() = 0;
//! Set pick object mode.
//! When object picked callback will be called, with OnPick
//! If pick operation is canceled Cancel will be called
//! @param targetClass specifies objects of which class are supposed to be picked
//! @param bMultipick if true pick tool will pick multiple object
virtual void PickObject(
IPickObjectCallback* callback,
const QMetaObject* targetClass = 0,
const char* statusText = 0,
bool bMultipick = false) = 0;
//! Cancel current pick operation
virtual void CancelPick() = 0;
//! Return true if editor now in object picking mode
virtual bool IsPicking() = 0;
//! Get DB manager that own items of specified type.
virtual IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) = 0;
//! Get Manager of Materials.
@@ -652,14 +622,6 @@ struct IEditor
//! editMode - EEditMode
virtual void SetEditMode(int editMode) = 0;
virtual int GetEditMode() = 0;
//! Assign current edit tool, destroy previously used edit too.
virtual void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) = 0;
//! Assign current edit tool by class name.
virtual void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) = 0;
//! Reinitializes the current edit tool if one is selected.
virtual void ReinitializeEditTool() = 0;
//! Returns current edit tool.
virtual CEditTool* GetEditTool() = 0;
//! Shows/Hides transformation manipulator.
//! if bShow is true also returns a valid ITransformManipulator pointer.
virtual ITransformManipulator* ShowTransformManipulator(bool bShow) = 0;
-192
View File
@@ -54,7 +54,6 @@ AZ_POP_DISABLE_WARNING
#include "Export/ExportManager.h"
#include "LevelIndependentFileMan.h"
#include "Material/MaterialManager.h"
#include "Material/MaterialPickTool.h"
#include "TrackView/TrackViewSequenceManager.h"
#include "AnimationContext.h"
#include "GameEngine.h"
@@ -65,20 +64,15 @@ AZ_POP_DISABLE_WARNING
#include "UIEnumsDatabase.h"
#include "Util/Ruler.h"
#include "RenderHelpers/AxisHelper.h"
#include "PickObjectTool.h"
#include "Settings.h"
#include "Include/IObjectManager.h"
#include "Include/ISourceControl.h"
#include "Objects/SelectionGroup.h"
#include "Objects/ObjectManager.h"
#include "RotateTool.h"
#include "NullEditTool.h"
#include "BackgroundTaskManager.h"
#include "BackgroundScheduleManager.h"
#include "EditorFileMonitor.h"
#include "EditMode/VertexSnappingModeTool.h"
#include "Mission.h"
#include "MainStatusBar.h"
@@ -170,7 +164,6 @@ CEditorImpl::CEditorImpl()
, m_pShaderEnum(nullptr)
, m_pIconManager(nullptr)
, m_bSelectionLocked(true)
, m_pPickTool(nullptr)
, m_pAxisGizmo(nullptr)
, m_pGameEngine(nullptr)
, m_pAnimationContext(nullptr)
@@ -453,12 +446,6 @@ void CEditorImpl::RegisterTools()
rc.pCommandManager = m_pCommandManager;
rc.pClassFactory = m_pClassFactory;
CObjectMode::RegisterTool(rc);
CMaterialPickTool::RegisterTool(rc);
CVertexSnappingModeTool::RegisterTool(rc);
CRotateTool::RegisterTool(rc);
NullEditTool::RegisterTool(rc);
}
void CEditorImpl::ExecuteCommand(const char* sCommand, ...)
@@ -684,14 +671,6 @@ void CEditorImpl::SetEditMode(int editMode)
}
}
if ((EEditMode)editMode == eEditModeRotate)
{
if (GetEditTool() && GetEditTool()->IsCircleTypeRotateGizmo())
{
editMode = eEditModeRotateCircle;
}
}
EEditMode newEditMode = (EEditMode)editMode;
if (m_currEditMode == newEditMode)
{
@@ -702,11 +681,6 @@ void CEditorImpl::SetEditMode(int editMode)
AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0));
SetSelectedRegion(box);
if (GetEditTool() && !GetEditTool()->IsNeedMoveTool())
{
SetEditTool(0, true);
}
Notify(eNotify_OnEditModeChange);
}
@@ -721,144 +695,6 @@ EOperationMode CEditorImpl::GetOperationMode()
return m_operationMode;
}
bool CEditorImpl::HasCorrectEditTool() const
{
if (!m_pEditTool)
{
return false;
}
switch (m_currEditMode)
{
case eEditModeRotate:
return qobject_cast<CRotateTool*>(m_pEditTool) != nullptr;
default:
return qobject_cast<CObjectMode*>(m_pEditTool) != nullptr && qobject_cast<CRotateTool*>(m_pEditTool) == nullptr;
}
}
CEditTool* CEditorImpl::CreateCorrectEditTool()
{
if (m_currEditMode == eEditModeRotate)
{
CBaseObject* selectedObj = nullptr;
CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
if (pSelection && pSelection->GetCount() > 0)
{
selectedObj = pSelection->GetObject(0);
}
return (new CRotateTool(selectedObj));
}
return (new CObjectMode);
}
void CEditorImpl::SetEditTool(CEditTool* tool, bool bStopCurrentTool)
{
CViewport* pViewport = GetIEditor()->GetActiveView();
if (pViewport)
{
pViewport->SetCurrentCursor(STD_CURSOR_DEFAULT);
}
if (!tool)
{
if (HasCorrectEditTool())
{
return;
}
else
{
tool = CreateCorrectEditTool();
}
}
if (!tool->Activate(m_pEditTool))
{
return;
}
if (bStopCurrentTool)
{
if (m_pEditTool && m_pEditTool != tool)
{
m_pEditTool->EndEditParams();
SetStatusText("Ready");
}
}
m_pEditTool = tool;
if (m_pEditTool)
{
m_pEditTool->BeginEditParams(this, 0);
}
// Make sure pick is aborted.
if (tool != m_pPickTool)
{
m_pPickTool = nullptr;
}
Notify(eNotify_OnEditToolChange);
}
void CEditorImpl::ReinitializeEditTool()
{
if (m_pEditTool)
{
m_pEditTool->EndEditParams();
m_pEditTool->BeginEditParams(this, 0);
}
}
void CEditorImpl::SetEditTool(const QString& sEditToolName, [[maybe_unused]] bool bStopCurrentTool)
{
CEditTool* pTool = GetEditTool();
if (pTool && pTool->GetClassDesc())
{
// Check if already selected.
if (QString::compare(pTool->GetClassDesc()->ClassName(), sEditToolName, Qt::CaseInsensitive) == 0)
{
return;
}
}
IClassDesc* pClass = GetIEditor()->GetClassFactory()->FindClass(sEditToolName.toUtf8().data());
if (!pClass)
{
Warning("Editor Tool %s not registered.", sEditToolName.toUtf8().data());
return;
}
if (pClass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL)
{
Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data());
return;
}
QScopedPointer<QObject> o(pClass->CreateQObject());
if (CEditTool* pEditTool = qobject_cast<CEditTool*>(o.data()))
{
GetIEditor()->SetEditTool(pEditTool);
o.take();
return;
}
else
{
Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data());
return;
}
}
CEditTool* CEditorImpl::GetEditTool()
{
if (m_isNewViewportInteractionModelEnabled)
{
return nullptr;
}
return m_pEditTool;
}
ITransformManipulator* CEditorImpl::ShowTransformManipulator(bool bShow)
{
if (bShow)
@@ -1069,34 +905,6 @@ bool CEditorImpl::IsSelectionLocked()
return m_bSelectionLocked;
}
void CEditorImpl::PickObject(IPickObjectCallback* callback, const QMetaObject* targetClass, const char* statusText, bool bMultipick)
{
m_pPickTool = new CPickObjectTool(callback, targetClass);
static_cast<CPickObjectTool*>(m_pPickTool.get())->SetMultiplePicks(bMultipick);
if (statusText)
{
m_pPickTool.get()->SetStatusText(statusText);
}
SetEditTool(m_pPickTool);
}
void CEditorImpl::CancelPick()
{
SetEditTool(0);
m_pPickTool = 0;
}
bool CEditorImpl::IsPicking()
{
if (GetEditTool() == m_pPickTool && m_pPickTool != 0)
{
return true;
}
return false;
}
CViewManager* CEditorImpl::GetViewManager()
{
return m_pViewManager;
-17
View File
@@ -181,10 +181,7 @@ public:
void SelectObject(CBaseObject* obj);
void LockSelection(bool bLock);
bool IsSelectionLocked();
void PickObject(IPickObjectCallback* callback, const QMetaObject* targetClass = 0, const char* statusText = 0, bool bMultipick = false);
void CancelPick();
bool IsPicking();
IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType);
CMaterialManager* GetMaterialManager() { return m_pMaterialManager; }
CMusicManager* GetMusicManager() { return m_pMusicManager; };
@@ -232,18 +229,6 @@ public:
void SetEditMode(int editMode);
int GetEditMode();
//! A correct tool is one that corresponds to the previously set edit mode.
bool HasCorrectEditTool() const;
//! Returns the edit tool required for the edit mode specified.
CEditTool* CreateCorrectEditTool();
void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) override;
void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) override;
void ReinitializeEditTool() override;
//! Returns current edit tool.
CEditTool* GetEditTool() override;
ITransformManipulator* ShowTransformManipulator(bool bShow);
ITransformManipulator* GetTransformManipulator();
void SetAxisConstraints(AxisConstrains axis);
@@ -403,13 +388,11 @@ protected:
CXmlTemplateRegistry m_templateRegistry;
CDisplaySettings* m_pDisplaySettings;
CShaderEnum* m_pShaderEnum;
_smart_ptr<CEditTool> m_pEditTool;
CIconManager* m_pIconManager;
std::unique_ptr<SGizmoParameters> m_pGizmoParameters;
QString m_primaryCDFolder;
QString m_userFolder;
bool m_bSelectionLocked;
_smart_ptr<CEditTool> m_pPickTool;
class CAxisGizmo* m_pAxisGizmo;
CGameEngine* m_pGameEngine;
CAnimationContext* m_pAnimationContext;
@@ -188,8 +188,6 @@ public:
virtual void SetSelection(const QString& name) = 0;
//! Removes one of named selections.
virtual void RemoveSelection(const QString& name) = 0;
//! Checks for changes to the current selection and makes adjustments accordingly
virtual void CheckAndFixSelection() = 0;
//! Delete all objects in current selection group.
virtual void DeleteSelection() = 0;
+11 -52
View File
@@ -25,7 +25,6 @@
#include "Objects/SelectionGroup.h"
#include "Include/IObjectManager.h"
#include "MathConversion.h"
#include "EditTool.h"
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_InfoBar.h>
@@ -58,7 +57,6 @@ CInfoBar::CInfoBar(QWidget* parent)
m_prevEditMode = 0;
m_bSelectionLocked = false;
m_bSelectionChanged = false;
m_editTool = 0;
m_bDragMode = false;
m_prevMoveSpeed = 0;
m_currValue = Vec3(-111, +222, -333); //this wasn't initialized. I don't know what a good value is
@@ -251,28 +249,6 @@ void CInfoBar::OnVectorUpdate(bool followTerrain)
ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator();
if (pManipulator)
{
CEditTool* pEditTool = GetIEditor()->GetEditTool();
if (pEditTool)
{
Vec3 diff = v - m_lastValue;
if (emode == eEditModeMove)
{
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
if (emode == eEditModeRotate)
{
diff = DEG2RAD(diff);
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
if (emode == eEditModeScale)
{
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
}
return;
}
@@ -421,39 +397,22 @@ void CInfoBar::IdleUpdate()
updateUI = true;
}
if (GetIEditor()->GetEditTool() != m_editTool)
{
updateUI = true;
m_editTool = GetIEditor()->GetEditTool();
}
QString str;
if (m_editTool)
{
str = m_editTool->GetStatusText();
if (str != m_sLastText)
{
updateUI = true;
}
}
if (updateUI)
{
if (!m_editTool)
if (m_numSelected == 0)
{
if (m_numSelected == 0)
{
str = tr("None Selected");
}
else if (m_numSelected == 1)
{
str = tr("1 Object Selected");
}
else
{
str = tr("%1 Objects Selected").arg(m_numSelected);
}
str = tr("None Selected");
}
else if (m_numSelected == 1)
{
str = tr("1 Object Selected");
}
else
{
str = tr("%1 Objects Selected").arg(m_numSelected);
}
ui->m_statusText->setText(str);
m_sLastText = str;
}
-1
View File
@@ -124,7 +124,6 @@ protected:
bool m_bDragMode;
QString m_sLastText;
CEditTool* m_editTool;
Vec3 m_lastValue;
Vec3 m_currValue;
float m_oldMainVolume;

Some files were not shown because too many files have changed in this diff Show More