Merge branch 'main' of https://github.com/aws-lumberyard/o3de into Spawnable/ScriptCanvas/Integration

This commit is contained in:
sconel
2021-05-25 10:43:56 -07:00
86 changed files with 2196 additions and 1504 deletions
@@ -0,0 +1,202 @@
"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
# fmt: off
class Tests():
new_event_created = ("New Script Event created", "New Script Event not created")
child_1_created = ("Initial Child Event created", "Initial Child Event not created")
child_2_created = ("Second Child Event created", "Second Child Event not created")
file_saved = ("Script event file saved", "Script event file did not save")
method_added = ("Method added to scriptevent file", "Method not added to scriptevent file")
method_removed = ("Method removed from scriptevent file", "Method not removed from scriptevent file")
# fmt: on
def ScriptEvent_AddRemoveMethod_UpdatesInSC():
"""
Summary:
Method can be added/removed to an existing .scriptevents file
Expected Behavior:
The Method is correctly added/removed to the asset, and Script Canvas nodes are updated accordingly.
Test Steps:
1) Open Asset Editor and Script Canvas windows
2) Initially create new Script Event file with one method
3) Verify if file is created and saved
4) Add a new child element
5) Update MethodNames and save file
6) Verify if the new node exist in SC (search in node palette)
7) Delete one method and save
8) Verify if the node is removed in SC
9) Close Asset Editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
from utils import TestHelper as helper
import pyside_utils
# Open 3D Engine imports
import azlmbr.legacy.general as general
import azlmbr.editor as editor
import azlmbr.bus as bus
# Pyside imports
from PySide2 import QtWidgets, QtTest, QtCore
GENERAL_WAIT = 1.0 # seconds
FILE_PATH = os.path.join("AutomatedTesting", "TestAssets", "test_file.scriptevents")
METHOD_NAME = "test_method_name"
editor_window = pyside_utils.get_editor_main_window()
asset_editor = asset_editor_widget = container = menu_bar = None
sc = node_palette = tree = search_frame = search_box = None
def initialize_asset_editor_qt_objects():
nonlocal asset_editor, asset_editor_widget, container, menu_bar
asset_editor = editor_window.findChild(QtWidgets.QDockWidget, "Asset Editor")
asset_editor_widget = asset_editor.findChild(QtWidgets.QWidget, "AssetEditorWindowClass")
container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
menu_bar = asset_editor_widget.findChild(QtWidgets.QMenuBar)
def initialize_sc_qt_objects():
nonlocal sc, node_palette, tree, search_frame, search_box
sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
if sc.findChild(QtWidgets.QDockWidget, "NodePalette") is None:
action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Palette", "type": QtWidgets.QAction})
action.trigger()
node_palette = sc.findChild(QtWidgets.QDockWidget, "NodePalette")
tree = node_palette.findChild(QtWidgets.QTreeView, "treeView")
search_frame = node_palette.findChild(QtWidgets.QFrame, "searchFrame")
search_box = search_frame.findChild(QtWidgets.QLineEdit, "searchFilter")
def save_file():
editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "iconText": "Save"})
action.trigger()
# wait till file is saved, to validate that check the text of QLabel at the bottom of the AssetEditor,
# if there are no unsaved changes we will not have any * in the text
label = asset_editor.findChild(QtWidgets.QLabel, "textEdit")
return helper.wait_for_condition(lambda: "*" not in label.text(), 3.0)
def expand_container_rows(object_name):
children = container.findChildren(QtWidgets.QFrame, object_name)
for child in children:
check_box = child.findChild(QtWidgets.QCheckBox)
if check_box and not check_box.isChecked():
QtTest.QTest.mouseClick(check_box, QtCore.Qt.LeftButton, QtCore.Qt.NoModifier)
def node_palette_search(node_name):
search_box.setText(node_name)
helper.wait_for_condition(lambda: search_box.text() == node_name, 1.0)
# Try clicking ENTER in search box multiple times
for _ in range(10):
QtTest.QTest.keyClick(search_box, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier)
if pyside_utils.find_child_by_pattern(tree, {"text": node_name}) is not None:
break
# 1) Open Asset Editor
general.idle_enable(True)
# Initially close the Asset Editor and then reopen to ensure we don't have any existing assets open
general.close_pane("Asset Editor")
general.open_pane("Asset Editor")
helper.wait_for_condition(lambda: general.is_pane_visible("Asset Editor"), 5.0)
# 2) Initially create new Script Event file with one method
initialize_asset_editor_qt_objects()
action = pyside_utils.find_child_by_pattern(menu_bar, {"type": QtWidgets.QAction, "text": "Script Events"})
action.trigger()
result = helper.wait_for_condition(
lambda: container.findChild(QtWidgets.QFrame, "Events") is not None
and container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "") is not None,
3 * GENERAL_WAIT,
)
Report.result(Tests.new_event_created, result)
# Add new method
add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
add_event.click()
result = helper.wait_for_condition(
lambda: asset_editor_widget.findChild(QtWidgets.QFrame, "EventName") is not None, GENERAL_WAIT
)
Report.result(Tests.child_1_created, result)
editor.AssetEditorWidgetRequestsBus(bus.Broadcast, "SaveAssetAs", FILE_PATH)
# 3) Verify if file is created and saved
result = helper.wait_for_condition(lambda: os.path.exists(FILE_PATH), 3 * GENERAL_WAIT)
Report.result(Tests.file_saved, result and save_file())
# 4) Add a new child element
add_event = container.findChild(QtWidgets.QFrame, "Events").findChild(QtWidgets.QToolButton, "")
add_event.click()
result = helper.wait_for_condition(
lambda: len(asset_editor_widget.findChildren(QtWidgets.QFrame, "EventName")) == 2, 2 * GENERAL_WAIT
)
Report.result(Tests.child_2_created, result)
# 5) Update MethodNames and save file, (update all Method names to make it easier to search in SC later)
# Expand the EventName initially
expand_container_rows("EventName")
# Expand Name fields under it
expand_container_rows("Name")
count = 0 # 2 Method names will be updated Ex: test_method_name_0, test_method_name_1
container = asset_editor_widget.findChild(QtWidgets.QWidget, "ContainerForRows")
children = container.findChildren(QtWidgets.QFrame, "Name")
for child in children:
line_edit = child.findChild(QtWidgets.QLineEdit)
if line_edit and line_edit.text() == "MethodName":
line_edit.setText(f"{METHOD_NAME}_{count}")
count += 1
save_file()
# 6) Verify if the new node exist in SC (search in node palette)
general.open_pane("Script Canvas")
helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0)
initialize_sc_qt_objects()
node_palette_search(f"{METHOD_NAME}_1")
get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": f"{METHOD_NAME}_1"}) is not None
result = helper.wait_for_condition(get_node_index, GENERAL_WAIT)
Report.result(Tests.method_added, result)
# 7) Delete one method and save
initialize_asset_editor_qt_objects()
for child in container.findChildren(QtWidgets.QFrame, "EventName"):
if child.findChild(QtWidgets.QToolButton, ""):
child.findChild(QtWidgets.QToolButton, "").click()
break
save_file()
# 8) Verify if the node is removed in SC (search in node palette)
initialize_sc_qt_objects()
node_palette_search(f"{METHOD_NAME}_0")
get_node_index = lambda: pyside_utils.find_child_by_pattern(tree, {"text": f"{METHOD_NAME}_0"}) is None
result = helper.wait_for_condition(get_node_index, GENERAL_WAIT)
Report.result(Tests.method_removed, result)
# 9) Close Asset Editor
general.close_pane("Asset Editor")
general.close_pane("Script Canvas")
if __name__ == "__main__":
import ImportPathHelper as imports
imports.init()
from utils import Report
Report.start_test(ScriptEvent_AddRemoveMethod_UpdatesInSC)
@@ -278,6 +278,7 @@ class TestScriptCanvasTests(object):
},
],
)
def test_Pane_PropertiesChanged_RetainsOnRestart(self, request, editor, config, project, launcher_platform):
hydra.launch_and_validate_results(
request,
@@ -289,3 +290,31 @@ class TestScriptCanvasTests(object):
auto_test_mode=False,
timeout=60,
)
def test_ScriptEvent_AddRemoveMethod_UpdatesInSC(self, request, workspace, editor, launcher_platform):
def teardown():
file_system.delete(
[os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
)
request.addfinalizer(teardown)
file_system.delete(
[os.path.join(workspace.paths.project(), "TestAssets", "test_file.scriptevents")], True, True
)
expected_lines = [
"Success: New Script Event created",
"Success: Initial Child Event created",
"Success: Second Child Event created",
"Success: Script event file saved",
"Success: Method added to scriptevent file",
"Success: Method removed from scriptevent file",
]
hydra.launch_and_validate_results(
request,
TEST_DIRECTORY,
editor,
"ScriptEvent_AddRemoveMethod_UpdatesInSC.py",
expected_lines,
auto_test_mode=False,
timeout=60,
)
@@ -60,6 +60,7 @@ namespace AzFramework
virtual void DrawTrianglesIndexed(const AZStd::vector<AZ::Vector3>& vertices, const AZStd::vector<AZ::u32>& indices, const AZ::Color& color) { (void)vertices; (void)indices, (void)color; }
virtual void DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) { (void)min; (void)max; }
virtual void DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) { (void)min; (void)max; }
virtual void DrawWireOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) { (void)center; (void)axisX; (void)axisY; (void)axisZ; (void)halfExtents; }
virtual void DrawSolidOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) { (void)center; (void)axisX; (void)axisY; (void)axisZ; (void)halfExtents; }
virtual void DrawPoint(const AZ::Vector3& p, int nSize = 1) { (void)p; (void)nSize; }
virtual void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) { (void)p1; (void)p2; }
@@ -70,18 +71,15 @@ namespace AzFramework
virtual void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) { (void)p1; (void)p2; (void)z; }
virtual void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) { (void)p1; (void)p2; (void)z; (void)firstColor; (void)secondColor; }
virtual void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) { (void)center; (void)radius; (void)z; }
virtual void DrawTerrainCircle(const AZ::Vector3& worldPos, float radius, float height) { (void)worldPos; (void)radius; (void)height; }
virtual void DrawTerrainCircle(const AZ::Vector3& center, float radius, float angle1, float angle2, float height) { (void)center; (void)radius; (void)angle1; (void)angle2; (void)height; }
virtual void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2) { (void)pos; (void)radius; (void)startAngleDegrees; (void)sweepAngleDegrees; (void)angularStepDegrees; (void)referenceAxis; }
virtual void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) { (void)pos; (void)radius; (void)startAngleDegrees; (void)sweepAngleDegrees; (void)angularStepDegrees; (void)fixedAxis; }
virtual void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) { (void)pos; (void)radius; (void)nUnchangedAxis; }
virtual void DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis = 2 /*z axis*/) { (void)pos; (void)radius; (void)viewPos; (void)nUnchangedAxis; }
virtual void DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) { (void)pos; (void)dir; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height) { (void)pos; (void)dir; (void)radius; (void)height; }
virtual void DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) { (void)pos; (void)dir; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) { (void)center; (void)axis; (void)radius; (void)height; }
virtual void DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded = true) { (void)center; (void)axis; (void)radius; (void)height; (void)drawShaded; }
virtual void DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float heightStraightSection) { (void)center; (void)axis; (void)radius; (void)heightStraightSection; }
virtual void DrawTerrainRect(float x1, float y1, float x2, float y2, float height) { (void)x1; (void)y1; (void)x2; (void)y2; (void)height; }
virtual void DrawTerrainLine(AZ::Vector3 worldPos1, AZ::Vector3 worldPos2) { (void)worldPos1; (void)worldPos2; }
virtual void DrawWireSphere(const AZ::Vector3& pos, float radius) { (void)pos; (void)radius; }
virtual void DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) { (void)pos; (void)radius; }
virtual void DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) { (void)pos; (void)dir; (void)radius; }
@@ -91,11 +89,8 @@ namespace AzFramework
virtual void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) { (void)pos; (void)size; (void)text; (void)bCenter; (void)srcOffsetX; (void)srcOffsetY; }
virtual void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) { (void)x; (void)y; (void)size; (void)text; (void)bCenter; }
virtual void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) { (void)pos; (void)text; (void)textScale; (void)TextColor; (void)TextBackColor; }
virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) { (void)texture; (void)pos; (void)sizeX; (void)sizeY; (void)texIconFlags; }
virtual void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) { (void)textureId; (void)pos; (void)sizeX; (void)sizeY; (void)texIconFlags; }
virtual void SetLineWidth(float width) { (void)width; }
virtual bool IsVisible(const AZ::Aabb& bounds) { (void)bounds; return false; }
virtual int SetFillMode(int nFillMode) { (void)nFillMode; return 0; }
virtual float GetLineWidth() { return 0.0f; }
virtual float GetAspectRatio() { return 0.0f; }
virtual void DepthTestOff() {}
@@ -81,9 +81,20 @@ namespace AzToolsFramework
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_" + name);
bool selectedAsset = false;
for (auto& assetId : selection.GetSelectedAssetIds())
{
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
if (assetId.IsValid())
{
selectedAsset = true;
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
}
}
if (!selectedAsset)
{
m_ui->m_assetBrowserTreeViewWidget->SelectFolder(selection.GetDefaultDirectory());
}
setWindowTitle(tr("Pick %1").arg(m_selection.GetTitle()));
@@ -93,6 +93,16 @@ namespace AzToolsFramework
m_selectedAssetIds.push_back(selectedAssetId);
}
void AssetSelectionModel::SetDefaultDirectory(AZStd::string_view defaultDirectory)
{
m_defaultDirectory = defaultDirectory;
}
AZStd::string_view AssetSelectionModel::GetDefaultDirectory() const
{
return m_defaultDirectory;
}
AZStd::vector<const AssetBrowserEntry*>& AssetSelectionModel::GetResults()
{
return m_results;
@@ -47,6 +47,9 @@ namespace AzToolsFramework
const AZStd::vector<AZ::Data::AssetId>& GetSelectedAssetIds() const;
void SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds);
void SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId);
void SetDefaultDirectory(AZStd::string_view defaultDirectory);
AZStd::string_view GetDefaultDirectory() const;
AZStd::vector<const AssetBrowserEntry*>& GetResults();
const AssetBrowserEntry* GetResult();
@@ -72,6 +75,7 @@ namespace AzToolsFramework
AZStd::vector<AZ::Data::AssetId> m_selectedAssetIds;
AZStd::vector<const AssetBrowserEntry*> m_results;
AZStd::string m_defaultDirectory;
QString m_title;
};
@@ -14,6 +14,7 @@
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzFramework/StringFunc/StringFunc.h>
@@ -270,7 +271,20 @@ namespace AzToolsFramework
return false;
}
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex)
void AssetBrowserTreeView::SelectFolder(AZStd::string_view folderPath)
{
if (folderPath.size() == 0)
{
return;
}
AZStd::vector<AZStd::string> entries;
AZ::StringFunc::Tokenize(folderPath, entries, "/");
SelectEntry(QModelIndex(), entries, 0, true);
}
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex, bool useDisplayName)
{
if (entries.empty())
{
@@ -285,30 +299,43 @@ namespace AzToolsFramework
auto rowIdx = model()->index(idx, 0, idxParent);
auto rowEntry = GetEntryFromIndex<AssetBrowserEntry>(rowIdx);
// Check if this entry name matches the query
if (rowEntry && AzFramework::StringFunc::Equal(entry.c_str(), rowEntry->GetName().c_str(), true))
if (rowEntry)
{
// Final entry found - set it as the selected element
if (entryPathIndex == entries.size() - 1)
{
selectionModel()->clear();
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
setCurrentIndex(rowIdx);
return true;
}
// Check if this entry name matches the query
AZStd::string_view compareName = useDisplayName ? (const char*)(rowEntry->GetDisplayName().toUtf8()) : rowEntry->GetName().c_str();
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
if (AzFramework::StringFunc::Equal(entry.c_str(), compareName, true))
{
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset Browser (otherwise, early out)
if (SelectEntry(rowIdx, entries, entryPathIndex + 1))
// Final entry found - set it as the selected element
if (entryPathIndex == entries.size() - 1)
{
expand(rowIdx);
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
{
// Expand the item itself if it is a folder
expand(rowIdx);
}
selectionModel()->clear();
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
setCurrentIndex(rowIdx);
return true;
}
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
{
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset
// Browser (otherwise, early out)
if (SelectEntry(rowIdx, entries, entryPathIndex + 1, useDisplayName))
{
expand(rowIdx);
return true;
}
}
return false;
}
return false;
}
}
@@ -60,6 +60,8 @@ namespace AzToolsFramework
AZStd::vector<AssetBrowserEntry*> GetSelectedAssets() const;
void SelectFolder(AZStd::string_view folderPath);
//////////////////////////////////////////////////////////////////////////
// AssetBrowserViewRequestBus
void SelectProduct(AZ::Data::AssetId assetID) override;
@@ -67,6 +69,7 @@ namespace AzToolsFramework
void ClearFilter() override;
void Update() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -105,7 +108,7 @@ namespace AzToolsFramework
QString m_name;
bool SelectProduct(const QModelIndex& idxParent, AZ::Data::AssetId assetID);
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0);
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0, bool useDisplayName = false);
//! Grab one entry from the source thumbnail list and update it
void UpdateSCThumbnails();
@@ -447,17 +447,14 @@ namespace AzToolsFramework
m_radius * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
// show wireframe if the axis has been corrected/flipped
// note: please see IRenderAuxGeom.h for the definition of e_FillModeWireframe and e_FillModeSolid.
// it is not possible to include IRenderAuxGeom from here and we also don't want to introduce that dependency.
// these legacy enums should be wrapped so set SetFillMode can be used in a type safe way, until then,
// use the values directly until the API has been updated.
const AZ::u32 prevFillMode = debugDisplay.SetFillMode(
m_shouldCorrect ? /*e_FillModeWireframe =*/ 0x1 << 26 : /*e_FillModeSolid =*/ 0);
debugDisplay.DrawCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height, false);
debugDisplay.SetFillMode(prevFillMode);
if (m_shouldCorrect)
{
debugDisplay.DrawWireCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height);
}
else
{
debugDisplay.DrawSolidCone(coneBound.m_base, coneBound.m_axis, coneBound.m_radius, coneBound.m_height, false);
}
RefreshBoundInternal(managerId, manipulatorId, coneBound);
}
@@ -769,6 +769,14 @@ namespace AzToolsFramework
// Request the AssetBrowser Dialog and set a type filter
AssetSelectionModel selection = GetAssetSelectionModel();
selection.SetSelectedAssetId(m_selectedAssetID);
AZStd::string defaultDirectory;
if (m_defaultDirectoryCallback)
{
m_defaultDirectoryCallback->Invoke(m_editNotifyTarget, defaultDirectory);
selection.SetDefaultDirectory(defaultDirectory);
}
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget());
if (selection.IsValid())
{
@@ -1080,6 +1088,11 @@ namespace AzToolsFramework
m_editNotifyCallback = editNotifyCallback;
}
void PropertyAssetCtrl::SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback)
{
m_defaultDirectoryCallback = callback;
}
void PropertyAssetCtrl::SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback)
{
m_clearNotifyCallback = clearNotifyCallback;
@@ -1214,6 +1227,11 @@ namespace AzToolsFramework
GUI->SetTitle(title.c_str());
}
}
else if (attrib == AZ_CRC_CE("DefaultStartingDirectoryCallback"))
{
// This is assumed to be an Asset Browser path to a specific folder to be used as a default by the asset picker if provided
GUI->SetDefaultDirectoryCallback(azdynamic_cast<PropertyAssetCtrl::DefaultDirectoryCallbackType*>(attrValue->GetAttribute()));
}
else if (attrib == AZ_CRC("EditCallback", 0xb74f2ee1))
{
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast<PropertyAssetCtrl::EditCallbackType*>(attrValue->GetAttribute());
@@ -68,6 +68,7 @@ namespace AzToolsFramework
// This is meant to be used with the "EditCallback" Attribute
using EditCallbackType = AZ::Edit::AttributeFunction<void(const AZ::Data::AssetId&, const AZ::Data::AssetType&)>;
using ClearCallbackType = AZ::Edit::AttributeFunction<void()>;
using DefaultDirectoryCallbackType = AZ::Edit::AttributeFunction<void(AZStd::string&)>;
PropertyAssetCtrl(QWidget *pParent = NULL, QString optionalValidDragDropExtensions = QString());
virtual ~PropertyAssetCtrl();
@@ -119,6 +120,7 @@ namespace AzToolsFramework
EditCallbackType* m_editNotifyCallback = nullptr;
ClearCallbackType* m_clearNotifyCallback = nullptr;
QString m_optionalValidDragDropExtensions;
DefaultDirectoryCallbackType* m_defaultDirectoryCallback = nullptr;
//! The number of characters after which the autocompleter dropdown will be shown.
// Prevents showing too many options.
@@ -196,6 +198,7 @@ namespace AzToolsFramework
void SetEditNotifyTarget(void* editNotifyTarget);
void SetEditNotifyCallback(EditCallbackType* editNotifyCallback); // This is meant to be used with the "EditCallback" Attribute
void SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback); // This is meant to be used with the "ClearNotify" Attribute
void SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback); // This is meant to be used with the "DefaultStartingDirectoryCallback" Attribute
void SetEditButtonEnabled(bool enabled);
void SetEditButtonVisible(bool visible);
void SetEditButtonIcon(const QIcon& icon);
@@ -233,9 +233,9 @@ namespace AzToolsFramework
}();
debugDisplay.SetColor(iconHighlight);
debugDisplay.DrawTextureLabel(
iconTextureId, entityPosition, iconSize, iconSize,
/*DisplayContext::ETextureIconFlags::TEXICON_ON_TOP=*/ 0x0008);
// debugDisplay.DrawTextureLabel(
// iconTextureId, entityPosition, iconSize, iconSize,
// /*DisplayContext::ETextureIconFlags::TEXICON_ON_TOP=*/ 0x0008);
}
}
}
+2 -4
View File
@@ -58,13 +58,11 @@
#include "LevelFileDialog.h"
#include "StatObjBus.h"
// LmbrCentral
#include <ModernViewportCameraController.h>
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <LmbrCentral/Rendering/EditorLightComponentBus.h> // for LmbrCentral::EditorLightComponentRequestBus
// LmbrCentral
#include <LmbrCentral/Rendering/EditorLightComponentBus.h> // for LmbrCentral::EditorLightComponentRequestBus
//#define PROFILE_LOADING_WITH_VTUNE
+2 -2
View File
@@ -53,6 +53,7 @@
// AtomToolsFramework
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
// CryCommon
#include <CryCommon/HMDBus.h>
@@ -75,7 +76,6 @@
#include "EditorPreferencesPageGeneral.h"
#include "ViewportManipulatorController.h"
#include "LegacyViewportCameraController.h"
#include "ModernViewportCameraController.h"
#include "EditorViewportSettings.h"
#include "ViewPane.h"
@@ -1220,7 +1220,7 @@ void EditorViewportWidget::SetViewportId(int id)
{
AzFramework::ReloadCameraKeyBindings();
auto controller = AZStd::make_shared<SandboxEditor::ModernViewportCameraController>();
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras)
{
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
+4
View File
@@ -34,6 +34,7 @@ CGotoPositionDlg::CGotoPositionDlg(QWidget* pParent /*=NULL*/)
{
m_ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setFixedSize(size());
OnInitDialog();
auto doubleValueChanged = static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
@@ -98,6 +99,9 @@ void CGotoPositionDlg::OnInitDialog()
m_ui->m_dymSegX->setVisible(false);
m_ui->m_dymSegY->setVisible(false);
// Ensure the goto button is highlighted correctly.
m_ui->pushButton->setDefault(true);
OnUpdateNumbers();
}
+199 -178
View File
@@ -6,189 +6,210 @@
<rect>
<x>0</x>
<y>0</y>
<width>358</width>
<height>198</height>
<width>290</width>
<height>180</height>
</rect>
</property>
<property name="windowTitle">
<string>Go to Position</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0,0,1,0,0,1">
<item row="6" column="0" colspan="2">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Go To</string>
</property>
</widget>
</item>
<item row="6" column="3" colspan="2">
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="5" column="6" colspan="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>22</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="m_dymZ"/>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="m_dymY"/>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="m_dymX"/>
</item>
<item row="4" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleY"/>
</item>
<item row="3" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleX"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="8">
<widget class="QLabel" name="label">
<property name="text">
<string>Enter position here:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="8">
<widget class="QLineEdit" name="m_posEdit">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Position:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QLabel" name="m_labelSegX">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleZ"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QLabel" name="m_labelSegY">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item row="3" column="5">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>22</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="3" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Angles:</string>
</property>
</widget>
</item>
<item row="2" column="6" colspan="2">
<widget class="QLabel" name="m_labelSeg">
<property name="text">
<string>Segments:</string>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QSpinBox" name="m_dymSegX"/>
</item>
<item row="4" column="7">
<widget class="QSpinBox" name="m_dymSegY"/>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0,0,1,0,0,1">
<item row="5" column="6" colspan="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>22</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="m_dymZ"/>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="m_dymY"/>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="m_dymX"/>
</item>
<item row="4" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleY"/>
</item>
<item row="3" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleX"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="8">
<widget class="QLabel" name="label">
<property name="text">
<string>Enter position here:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="8">
<widget class="QLineEdit" name="m_posEdit">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Position:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QLabel" name="m_labelSegX">
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QDoubleSpinBox" name="m_dymAngleZ"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QLabel" name="m_labelSegY">
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item row="3" column="5">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>22</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="3" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Angles:</string>
</property>
</widget>
</item>
<item row="2" column="6" colspan="2">
<widget class="QLabel" name="m_labelSeg">
<property name="text">
<string>Segments:</string>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QSpinBox" name="m_dymSegX"/>
</item>
<item row="4" column="7">
<widget class="QSpinBox" name="m_dymSegY"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="buttonLayout">
<item>
<spacer name="horizontalSpacer_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Go To</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_posEdit</tabstop>
@@ -823,9 +823,6 @@ set(FILES
ViewportManipulatorController.h
LegacyViewportCameraController.cpp
LegacyViewportCameraController.h
ModernViewportCameraController.cpp
ModernViewportCameraController.h
ModernViewportCameraControllerRequestBus.h
RenderViewport.cpp
RenderViewport.h
TopRendererWnd.cpp
@@ -38,6 +38,7 @@ ly_add_target(
Gem::LmbrCentral
AZ::AtomCore
Gem::Atom_RPI.Public
Gem::AtomToolsFramework.Static
)
ly_add_dependencies(Editor ComponentEntityEditorPlugin)
@@ -66,8 +66,8 @@
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h>
#include <ModernViewportCameraControllerRequestBus.h>
#include "Objects/ComponentEntityObject.h"
#include "ISourceControl.h"
@@ -382,11 +382,6 @@ void SandboxIntegrationManager::Teardown()
{
AzToolsFramework::Layers::EditorLayerComponentNotificationBus::Handler::BusDisconnect();
AzFramework::DisplayContextRequestBus::Handler::BusDisconnect();
if( m_debugDisplayBusImplementationActive)
{
AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect();
m_debugDisplayBusImplementationActive = false;
}
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
@@ -1741,9 +1736,9 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
const AZ::Transform nextCameraTransform =
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToTarget), aabb.GetCenter());
SandboxEditor::ModernViewportCameraControllerRequestBus::Event(
viewportContext->GetId(), &SandboxEditor::ModernViewportCameraControllerRequestBus::Events::InterpolateToTransform,
nextCameraTransform);
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
viewportContext->GetId(),
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform);
}
}
}
@@ -2041,678 +2036,6 @@ void SandboxIntegrationManager::BrowseForAssets(AssetSelectionModel& selection)
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, GetMainWindow());
}
void SandboxIntegrationManager::SetColor(float r, float g, float b, float a)
{
if (m_dc)
{
m_dc->SetColor(Vec3(r, g, b), a);
}
}
void SandboxIntegrationManager::SetColor(const AZ::Color& color)
{
if (m_dc)
{
m_dc->SetColor(AZColorToLYColorF(color));
}
}
void SandboxIntegrationManager::SetColor(const AZ::Vector4& color)
{
if (m_dc)
{
m_dc->SetColor(AZVec3ToLYVec3(color.GetAsVector3()), color.GetW());
}
}
void SandboxIntegrationManager::SetAlpha(float a)
{
if (m_dc)
{
m_dc->SetAlpha(a);
}
}
void SandboxIntegrationManager::DrawQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4)
{
if (m_dc)
{
m_dc->DrawQuad(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2),
AZVec3ToLYVec3(p3),
AZVec3ToLYVec3(p4));
}
}
void SandboxIntegrationManager::DrawQuad(float width, float height)
{
if (m_dc)
{
m_dc->DrawQuad(width, height);
}
}
void SandboxIntegrationManager::DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4)
{
if (m_dc)
{
m_dc->DrawWireQuad(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2),
AZVec3ToLYVec3(p3),
AZVec3ToLYVec3(p4));
}
}
void SandboxIntegrationManager::DrawWireQuad(float width, float height)
{
if (m_dc)
{
m_dc->DrawWireQuad(width, height);
}
}
void SandboxIntegrationManager::DrawQuadGradient(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor)
{
if (m_dc)
{
m_dc->DrawQuadGradient(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2),
AZVec3ToLYVec3(p3),
AZVec3ToLYVec3(p4),
ColorF(AZVec3ToLYVec3(firstColor.GetAsVector3()), firstColor.GetW()),
ColorF(AZVec3ToLYVec3(secondColor.GetAsVector3()), secondColor.GetW()));
}
}
void SandboxIntegrationManager::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3)
{
if (m_dc)
{
m_dc->DrawTri(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2),
AZVec3ToLYVec3(p3));
}
}
void SandboxIntegrationManager::DrawTriangles(const AZStd::vector<AZ::Vector3>& vertices, const AZ::Color& color)
{
if (m_dc)
{
// transform to world space
const auto vecTransform = [this](const AZ::Vector3& vec)
{
return m_dc->GetMatrix() * AZVec3ToLYVec3(vec);
};
AZStd::vector<Vec3> cryVertices;
cryVertices.reserve(vertices.size());
AZStd::transform(vertices.begin(), vertices.end(), AZStd::back_inserter(cryVertices), vecTransform);
m_dc->DrawTriangles(
cryVertices,
AZColorToLYColorF(color));
}
}
void SandboxIntegrationManager::DrawTrianglesIndexed(const AZStd::vector<AZ::Vector3>& vertices, const AZStd::vector<AZ::u32>& indices, const AZ::Color& color)
{
if (m_dc)
{
// transform to world space
const auto vecTransform = [this](const AZ::Vector3& vec)
{
return m_dc->GetMatrix() * AZVec3ToLYVec3(vec);
};
AZStd::vector<Vec3> cryVertices;
cryVertices.reserve(vertices.size());
AZStd::transform(vertices.begin(), vertices.end(), AZStd::back_inserter(cryVertices), vecTransform);
m_dc->DrawTrianglesIndexed(
cryVertices,
indices,
AZColorToLYColorF(color));
}
}
void SandboxIntegrationManager::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max)
{
if (m_dc)
{
m_dc->DrawWireBox(
AZVec3ToLYVec3(min),
AZVec3ToLYVec3(max));
}
}
void SandboxIntegrationManager::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max)
{
if (m_dc)
{
m_dc->DrawSolidBox(
AZVec3ToLYVec3(min),
AZVec3ToLYVec3(max));
}
}
void SandboxIntegrationManager::DrawSolidOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents)
{
if (m_dc)
{
m_dc->DrawSolidOBB(AZVec3ToLYVec3(center), AZVec3ToLYVec3(axisX), AZVec3ToLYVec3(axisY), AZVec3ToLYVec3(axisZ), AZVec3ToLYVec3(halfExtents));
}
}
void SandboxIntegrationManager::DrawPoint(const AZ::Vector3& p, int nSize)
{
if (m_dc)
{
m_dc->DrawPoint(AZVec3ToLYVec3(p), nSize);
}
}
void SandboxIntegrationManager::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2)
{
if (m_dc)
{
m_dc->DrawLine(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2));
}
}
void SandboxIntegrationManager::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2)
{
if (m_dc)
{
m_dc->DrawLine(
AZVec3ToLYVec3(p1),
AZVec3ToLYVec3(p2),
ColorF(AZVec3ToLYVec3(col1.GetAsVector3()), col1.GetW()),
ColorF(AZVec3ToLYVec3(col2.GetAsVector3()), col2.GetW()));
}
}
void SandboxIntegrationManager::DrawLines(const AZStd::vector<AZ::Vector3>& lines, const AZ::Color& color)
{
if (m_dc)
{
// transform to world space
const auto vecTransform = [this](const AZ::Vector3& vec)
{
return m_dc->GetMatrix() * AZVec3ToLYVec3(vec);
};
AZStd::vector<Vec3> cryLines;
cryLines.reserve(cryLines.size());
AZStd::transform(lines.begin(), lines.end(), AZStd::back_inserter(cryLines), vecTransform);
m_dc->DrawLines(cryLines, AZColorToLYColorF(color));
}
}
void SandboxIntegrationManager::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled)
{
if (m_dc)
{
Vec3* points = new Vec3[numPoints];
for (int i = 0; i < numPoints; ++i)
{
points[i] = AZVec3ToLYVec3(pnts[i]);
}
m_dc->DrawPolyLine(points, numPoints, cycled);
delete[] points;
}
}
void SandboxIntegrationManager::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z)
{
if (m_dc)
{
m_dc->DrawWireQuad2d(
QPoint(static_cast<int>(p1.GetX()), static_cast<int>(p1.GetY())),
QPoint(static_cast<int>(p2.GetX()), static_cast<int>(p2.GetY())),
z);
}
}
void SandboxIntegrationManager::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z)
{
if (m_dc)
{
m_dc->DrawLine2d(
QPoint(static_cast<int>(p1.GetX()), static_cast<int>(p1.GetY())),
QPoint(static_cast<int>(p2.GetX()), static_cast<int>(p2.GetY())),
z);
}
}
void SandboxIntegrationManager::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor)
{
if (m_dc)
{
m_dc->DrawLine2dGradient(
QPoint(static_cast<int>(p1.GetX()), static_cast<int>(p1.GetY())),
QPoint(static_cast<int>(p2.GetX()), static_cast<int>(p2.GetY())),
z,
ColorF(AZVec3ToLYVec3(firstColor.GetAsVector3()), firstColor.GetW()),
ColorF(AZVec3ToLYVec3(secondColor.GetAsVector3()), secondColor.GetW()));
}
}
void SandboxIntegrationManager::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z)
{
if (m_dc)
{
m_dc->DrawWireCircle2d(
QPoint(static_cast<int>(center.GetX()), static_cast<int>(center.GetY())),
radius, z);
}
}
void SandboxIntegrationManager::DrawTerrainCircle(const AZ::Vector3& worldPos, float radius, float height)
{
if (m_dc)
{
m_dc->DrawTerrainCircle(
AZVec3ToLYVec3(worldPos), radius, height);
}
}
void SandboxIntegrationManager::DrawTerrainCircle(const AZ::Vector3& center, float radius, float angle1, float angle2, float height)
{
if (m_dc)
{
m_dc->DrawTerrainCircle(
AZVec3ToLYVec3(center), radius, angle1, angle2, height);
}
}
void SandboxIntegrationManager::DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis)
{
if (m_dc)
{
m_dc->DrawArc(
AZVec3ToLYVec3(pos),
radius,
startAngleDegrees,
sweepAngleDegrees,
angularStepDegrees,
referenceAxis);
}
}
void SandboxIntegrationManager::DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis)
{
if (m_dc)
{
m_dc->DrawArc(
AZVec3ToLYVec3(pos),
radius,
startAngleDegrees,
sweepAngleDegrees,
angularStepDegrees,
AZVec3ToLYVec3(fixedAxis));
}
}
void SandboxIntegrationManager::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis)
{
if (m_dc)
{
m_dc->DrawCircle(
AZVec3ToLYVec3(pos),
radius,
nUnchangedAxis);
}
}
void SandboxIntegrationManager::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis)
{
if (m_dc)
{
m_dc->DrawHalfDottedCircle(
AZVec3ToLYVec3(pos),
radius,
AZVec3ToLYVec3(viewPos),
nUnchangedAxis);
}
}
void SandboxIntegrationManager::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded)
{
if (m_dc)
{
m_dc->DrawCone(
AZVec3ToLYVec3(pos),
AZVec3ToLYVec3(dir),
radius,
height,
drawShaded);
}
}
void SandboxIntegrationManager::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height)
{
if (m_dc)
{
m_dc->DrawWireCylinder(
AZVec3ToLYVec3(center),
AZVec3ToLYVec3(axis),
radius,
height);
}
}
void SandboxIntegrationManager::DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded)
{
if (m_dc)
{
m_dc->DrawSolidCylinder(
AZVec3ToLYVec3(center),
AZVec3ToLYVec3(axis),
radius,
height,
drawShaded);
}
}
void SandboxIntegrationManager::DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height)
{
if (m_dc)
{
m_dc->DrawWireCapsule(
AZVec3ToLYVec3(center),
AZVec3ToLYVec3(axis),
radius,
height);
}
}
void SandboxIntegrationManager::DrawTerrainRect(float x1, float y1, float x2, float y2, float height)
{
if (m_dc)
{
m_dc->DrawTerrainRect(x1, y1, x2, y2, height);
}
}
void SandboxIntegrationManager::DrawTerrainLine(AZ::Vector3 worldPos1, AZ::Vector3 worldPos2)
{
if (m_dc)
{
m_dc->DrawTerrainLine(
AZVec3ToLYVec3(worldPos1),
AZVec3ToLYVec3(worldPos2));
}
}
void SandboxIntegrationManager::DrawWireSphere(const AZ::Vector3& pos, float radius)
{
if (m_dc)
{
m_dc->DrawWireSphere(AZVec3ToLYVec3(pos), radius);
}
}
void SandboxIntegrationManager::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius)
{
if (m_dc)
{
m_dc->DrawWireSphere(
AZVec3ToLYVec3(pos),
AZVec3ToLYVec3(radius));
}
}
void SandboxIntegrationManager::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius)
{
if (m_dc)
{
m_dc->DrawWireDisk(
AZVec3ToLYVec3(pos),
AZVec3ToLYVec3(dir),
radius);
}
}
void SandboxIntegrationManager::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded)
{
if (m_dc)
{
m_dc->DrawBall(AZVec3ToLYVec3(pos), radius, drawShaded);
}
}
void SandboxIntegrationManager::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius)
{
if (m_dc)
{
m_dc->DrawDisk(
AZVec3ToLYVec3(pos),
AZVec3ToLYVec3(dir),
radius);
}
}
void SandboxIntegrationManager::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float fHeadScale, bool b2SidedArrow)
{
if (m_dc)
{
m_dc->DrawArrow(
AZVec3ToLYVec3(src),
AZVec3ToLYVec3(trg),
fHeadScale,
b2SidedArrow);
}
}
void SandboxIntegrationManager::DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter, int srcOffsetX, int srcOffsetY)
{
if (m_dc)
{
m_dc->DrawTextLabel(
AZVec3ToLYVec3(pos),
size,
text,
bCenter,
srcOffsetX,
srcOffsetY);
}
}
void SandboxIntegrationManager::Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter)
{
if (m_dc)
{
m_dc->Draw2dTextLabel(x, y, size, text, bCenter);
}
}
void SandboxIntegrationManager::DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags)
{
if (m_dc)
{
if (texture)
{
float textureWidth = aznumeric_caster(texture->GetWidth());
float textureHeight = aznumeric_caster(texture->GetHeight());
// resize the label in proportion to the actual texture size
if (textureWidth > textureHeight)
{
sizeY = sizeX * (textureHeight / textureWidth);
}
else
{
sizeX = sizeY * (textureWidth / textureHeight);
}
m_dc->DrawTextureLabel(AZVec3ToLYVec3(pos), sizeX, sizeY, texture->GetTextureID(), texIconFlags);
}
}
}
void SandboxIntegrationManager::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags)
{
// ToDo: With Atom?
AZ_UNUSED(textureId);
AZ_UNUSED(pos);
AZ_UNUSED(sizeX);
AZ_UNUSED(sizeY);
AZ_UNUSED(texIconFlags);
}
void SandboxIntegrationManager::SetLineWidth(float width)
{
if (m_dc)
{
m_dc->SetLineWidth(width);
}
}
bool SandboxIntegrationManager::IsVisible(const AZ::Aabb& bounds)
{
if (m_dc)
{
const AABB aabb(
AZVec3ToLYVec3(bounds.GetMin()),
AZVec3ToLYVec3(bounds.GetMax()));
return m_dc->IsVisible(aabb);
}
return 0;
}
int SandboxIntegrationManager::SetFillMode(int nFillMode)
{
if (m_dc)
{
return m_dc->SetFillMode(nFillMode);
}
return 0;
}
float SandboxIntegrationManager::GetLineWidth()
{
if (m_dc)
{
return m_dc->GetLineWidth();
}
return 0.f;
}
float SandboxIntegrationManager::GetAspectRatio()
{
if (m_dc && m_dc->GetView())
{
return m_dc->GetView()->GetAspectRatio();
}
return 0.f;
}
void SandboxIntegrationManager::DepthTestOff()
{
if (m_dc)
{
m_dc->DepthTestOff();
}
}
void SandboxIntegrationManager::DepthTestOn()
{
if (m_dc)
{
m_dc->DepthTestOn();
}
}
void SandboxIntegrationManager::DepthWriteOff()
{
if (m_dc)
{
m_dc->DepthWriteOff();
}
}
void SandboxIntegrationManager::DepthWriteOn()
{
if (m_dc)
{
m_dc->DepthWriteOn();
}
}
void SandboxIntegrationManager::CullOff()
{
if (m_dc)
{
m_dc->CullOff();
}
}
void SandboxIntegrationManager::CullOn()
{
if (m_dc)
{
m_dc->CullOn();
}
}
bool SandboxIntegrationManager::SetDrawInFrontMode(bool bOn)
{
if (m_dc)
{
return m_dc->SetDrawInFrontMode(bOn);
}
return 0.f;
}
AZ::u32 SandboxIntegrationManager::GetState()
{
if (m_dc)
{
return m_dc->GetState();
}
return 0;
}
AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state)
{
if (m_dc)
{
return m_dc->SetState(state);
}
return 0;
}
void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm)
{
if (m_dc)
{
const Matrix34 m = AZTransformToLYTransform(tm);
m_dc->PushMatrix(m);
}
}
void SandboxIntegrationManager::PopMatrix()
{
if (m_dc)
{
m_dc->PopMatrix();
}
}
bool SandboxIntegrationManager::DisplayHelpersVisible()
{
return GetIEditor()->GetDisplaySettings()->IsDisplayHelpers();
@@ -100,7 +100,6 @@ class SandboxIntegrationManager
, private AzToolsFramework::EditorEvents::Bus::Handler
, private AzToolsFramework::EditorWindowRequests::Bus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
, private AzFramework::DebugDisplayRequestBus::Handler
, private AzFramework::DisplayContextRequestBus::Handler
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
, private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
@@ -202,70 +201,6 @@ private:
const AzFramework::SliceInstantiationTicket& ticket) override;
//////////////////////////////////////////////////////////////////////////
// AzToolsFramework::DebugDisplayRequestBus
void SetColor(float r, float g, float b, float a) override;
void SetColor(const AZ::Color& color) override;
void SetColor(const AZ::Vector4& color) override;
void SetAlpha(float a) override;
void DrawQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override;
void DrawQuad(float width, float height) override;
void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override;
void DrawWireQuad(float width, float height) override;
void DrawQuadGradient(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override;
void DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) override;
void DrawTriangles(const AZStd::vector<AZ::Vector3>& vertices, const AZ::Color& color) override;
void DrawTrianglesIndexed(const AZStd::vector<AZ::Vector3>& vertices, const AZStd::vector<AZ::u32>& indices, const AZ::Color& color) override;
void DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) override;
void DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) override;
void DrawSolidOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) override;
void DrawPoint(const AZ::Vector3& p, int nSize) override;
void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) override;
void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) override;
void DrawLines(const AZStd::vector<AZ::Vector3>& lines, const AZ::Color& color) override;
void DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled) override;
void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override;
void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override;
void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override;
void DrawTerrainCircle(const AZ::Vector3& worldPos, float radius, float height) override;
void DrawTerrainCircle(const AZ::Vector3& center, float radius, float angle1, float angle2, float height) override;
void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis) override;
void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) override;
void DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded = true) override;
void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis) override;
void DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis) override;
void DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) override;
void DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded = true) override;
void DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) override;
void DrawTerrainRect(float x1, float y1, float x2, float y2, float height) override;
void DrawTerrainLine(AZ::Vector3 worldPos1, AZ::Vector3 worldPos2) override;
void DrawWireSphere(const AZ::Vector3& pos, float radius) override;
void DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) override;
void DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) override;
void DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded = true) override;
void DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) override;
void DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float fHeadScale, bool b2SidedArrow) override;
void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter, int srcOffsetX, int scrOffsetY) override;
void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter) override;
void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
void SetLineWidth(float width) override;
bool IsVisible(const AZ::Aabb& bounds) override;
int SetFillMode(int nFillMode) override;
float GetLineWidth() override;
float GetAspectRatio() override;
void DepthTestOff() override;
void DepthTestOn() override;
void DepthWriteOff() override;
void DepthWriteOn() override;
void CullOff() override;
void CullOn() override;
bool SetDrawInFrontMode(bool bOn) override;
AZ::u32 GetState() override;
AZ::u32 SetState(AZ::u32 state) override;
void PushMatrix(const AZ::Transform& tm) override;
void PopMatrix() override;
// AzFramework::DisplayContextRequestBus (and @deprecated EntityDebugDisplayRequestBus)
// AzFramework::DisplayContextRequestBus
void SetDC(DisplayContext* dc) override;
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f82f22df64b93d4bec91e56b60efa3d5ce2915ce388a2dc627f1ab720678e3d5
size 334987
@@ -11,6 +11,9 @@
<file>iOS.svg</file>
<file>Linux.svg</file>
<file>macOS.svg</file>
<file>DefaultProjectImage.png</file>
<file>ArrowDownLine.svg</file>
<file>ArrowUpLine.svg</file>
<file>Backgrounds/FirstTimeBackgroundImage.jpg</file>
</qresource>
</RCC>
@@ -10,7 +10,7 @@
*
*/
#include <ProjectSettingsCtrl.h>
#include <CreateProjectCtrl.h>
#include <ScreensCtrl.h>
#include <PythonBindingsInterface.h>
#include <NewProjectSettingsScreen.h>
@@ -22,7 +22,7 @@
namespace O3DE::ProjectManager
{
ProjectSettingsCtrl::ProjectSettingsCtrl(QWidget* parent)
CreateProjectCtrl::CreateProjectCtrl(QWidget* parent)
: ScreenWidget(parent)
{
QVBoxLayout* vLayout = new QVBoxLayout();
@@ -34,11 +34,11 @@ namespace O3DE::ProjectManager
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
vLayout->addWidget(backNextButtons);
m_backButton = backNextButtons->addButton("Back", QDialogButtonBox::RejectRole);
m_nextButton = backNextButtons->addButton("Next", QDialogButtonBox::ApplyRole);
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
connect(m_backButton, &QPushButton::pressed, this, &ProjectSettingsCtrl::HandleBackButton);
connect(m_nextButton, &QPushButton::pressed, this, &ProjectSettingsCtrl::HandleNextButton);
connect(m_backButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleBackButton);
connect(m_nextButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleNextButton);
m_screensOrder =
{
@@ -47,15 +47,16 @@ namespace O3DE::ProjectManager
};
m_screensCtrl->BuildScreens(m_screensOrder);
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::NewProjectSettings, false);
UpdateNextButtonText();
}
ProjectManagerScreen ProjectSettingsCtrl::GetScreenEnum()
ProjectManagerScreen CreateProjectCtrl::GetScreenEnum()
{
return ProjectManagerScreen::NewProjectSettingsCore;
return ProjectManagerScreen::CreateProject;
}
void ProjectSettingsCtrl::HandleBackButton()
void CreateProjectCtrl::HandleBackButton()
{
if (!m_screensCtrl->GotoPreviousScreen())
{
@@ -66,7 +67,7 @@ namespace O3DE::ProjectManager
UpdateNextButtonText();
}
}
void ProjectSettingsCtrl::HandleNextButton()
void CreateProjectCtrl::HandleNextButton()
{
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
@@ -116,9 +117,14 @@ namespace O3DE::ProjectManager
}
}
void ProjectSettingsCtrl::UpdateNextButtonText()
void CreateProjectCtrl::UpdateNextButtonText()
{
m_nextButton->setText(m_screensCtrl->GetCurrentScreen()->GetNextButtonText());
QString nextButtonText = tr("Next");
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
{
nextButtonText = tr("Create Project");
}
m_nextButton->setText(nextButtonText);
}
} // namespace O3DE::ProjectManager
@@ -21,12 +21,12 @@
namespace O3DE::ProjectManager
{
class ProjectSettingsCtrl
class CreateProjectCtrl
: public ScreenWidget
{
public:
explicit ProjectSettingsCtrl(QWidget* parent = nullptr);
~ProjectSettingsCtrl() = default;
explicit CreateProjectCtrl(QWidget* parent = nullptr);
~CreateProjectCtrl() = default;
ProjectManagerScreen GetScreenEnum() override;
protected slots:
@@ -21,13 +21,6 @@
namespace O3DE::ProjectManager
{
inline constexpr static int s_contentMargins = 80;
inline constexpr static int s_buttonSpacing = 30;
inline constexpr static int s_iconSize = 24;
inline constexpr static int s_spacerSize = 20;
inline constexpr static int s_boxButtonWidth = 210;
inline constexpr static int s_boxButtonHeight = 280;
FirstTimeUseScreen::FirstTimeUseScreen(QWidget* parent)
: ScreenWidget(parent)
{
@@ -79,8 +72,8 @@ namespace O3DE::ProjectManager
void FirstTimeUseScreen::HandleNewProjectButton()
{
emit ResetScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
emit ChangeScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
}
void FirstTimeUseScreen::HandleAddProjectButton()
{
@@ -37,6 +37,13 @@ namespace O3DE::ProjectManager
QPushButton* m_createProjectButton;
QPushButton* m_addProjectButton;
inline constexpr static int s_contentMargins = 80;
inline constexpr static int s_buttonSpacing = 30;
inline constexpr static int s_iconSize = 24;
inline constexpr static int s_spacerSize = 20;
inline constexpr static int s_boxButtonWidth = 210;
inline constexpr static int s_boxButtonHeight = 280;
};
} // namespace O3DE::ProjectManager
@@ -12,6 +12,8 @@
#include <GemCatalog/GemCatalogScreen.h>
#include <PythonBindingsInterface.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <GemCatalog/GemFilterWidget.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
@@ -25,15 +27,18 @@ namespace O3DE::ProjectManager
: ScreenWidget(parent)
{
m_gemModel = new GemModel(this);
GemSortFilterProxyModel* proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0);
vLayout->setSpacing(0);
setLayout(vLayout);
QHBoxLayout* hLayout = new QHBoxLayout();
hLayout->setMargin(0);
vLayout->addLayout(hLayout);
m_gemListView = new GemListView(m_gemModel, this);
m_gemListView = new GemListView(proxyModel, proxyModel->GetSelectionModel(), this);
m_gemInspector = new GemInspector(m_gemModel, this);
m_gemInspector->setFixedWidth(320);
@@ -56,8 +61,19 @@ namespace O3DE::ProjectManager
}
#endif
hLayout->addWidget(m_gemListView);
GemFilterWidget* filterWidget = new GemFilterWidget(proxyModel);
filterWidget->setFixedWidth(250);
QVBoxLayout* middleVLayout = new QVBoxLayout();
middleVLayout->setMargin(0);
middleVLayout->setSpacing(0);
middleVLayout->addWidget(m_gemListView);
hLayout->addWidget(filterWidget);
hLayout->addLayout(middleVLayout);
hLayout->addWidget(m_gemInspector);
proxyModel->InvalidateFilter();
}
QVector<GemInfo> GemCatalogScreen::GenerateTestData()
@@ -73,10 +89,12 @@ namespace O3DE::ProjectManager
gem.m_documentationLink = "http://www.amazon.com";
gem.m_dependingGemUuids = QStringList({"EMotionFX", "Atom"});
gem.m_conflictingGemUuids = QStringList({"Vegetation", "Camera", "ScriptCanvas", "CloudCanvas", "Networking"});
gem.m_types = (GemInfo::Code | GemInfo::Asset);
gem.m_version = "v1.01";
gem.m_lastUpdatedDate = "24th April 2021";
gem.m_binarySizeInKB = 40;
gem.m_features = QStringList({"Animation", "Assets", "Physics"});
gem.m_gemOrigin = GemInfo::O3DEFoundation;
result.push_back(gem);
gem.m_name = "Atom";
@@ -152,9 +170,4 @@ namespace O3DE::ProjectManager
{
return ProjectManagerScreen::GemCatalog;
}
QString GemCatalogScreen::GetNextButtonText()
{
return "Create Project";
}
} // namespace O3DE::ProjectManager
@@ -9,6 +9,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
@@ -27,7 +28,6 @@ namespace O3DE::ProjectManager
explicit GemCatalogScreen(QWidget* parent = nullptr);
~GemCatalogScreen() = default;
ProjectManagerScreen GetScreenEnum() override;
QString GetNextButtonText() override;
private:
QVector<GemInfo> GenerateTestData();
@@ -0,0 +1,412 @@
/*
* 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 <GemCatalog/GemFilterWidget.h>
#include <QButtonGroup>
#include <QCheckBox>
#include <QLabel>
#include <QMap>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
namespace O3DE::ProjectManager
{
FilterCategoryWidget::FilterCategoryWidget(const QString& header,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
bool showAllLessButton,
int defaultShowCount,
QWidget* parent)
: QWidget(parent)
, m_defaultShowCount(defaultShowCount)
{
AZ_Assert(elementNames.size() == elementCounts.size(), "Number of element names needs to match the counts.");
QVBoxLayout* vLayout = new QVBoxLayout();
setLayout(vLayout);
// Collapse button
QHBoxLayout* collapseLayout = new QHBoxLayout();
m_collapseButton = new QPushButton();
m_collapseButton->setCheckable(true);
m_collapseButton->setFlat(true);
m_collapseButton->setFocusPolicy(Qt::NoFocus);
m_collapseButton->setFixedWidth(s_collapseButtonSize);
m_collapseButton->setStyleSheet("border: 0px; border-radius: 0px;");
connect(m_collapseButton, &QPushButton::clicked, this, [=]()
{
UpdateCollapseState();
});
collapseLayout->addWidget(m_collapseButton);
// Category title
QLabel* headerLabel = new QLabel(header);
headerLabel->setStyleSheet("font-size: 11pt;");
collapseLayout->addWidget(headerLabel);
vLayout->addLayout(collapseLayout);
vLayout->addSpacing(5);
// Everything in the main widget will be collapsed/uncollapsed
{
m_mainWidget = new QWidget();
vLayout->addWidget(m_mainWidget);
QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setAlignment(Qt::AlignTop);
m_mainWidget->setLayout(mainLayout);
// Elements
m_buttonGroup = new QButtonGroup();
m_buttonGroup->setExclusive(false);
for (int i = 0; i < elementNames.size(); ++i)
{
QWidget* elementWidget = new QWidget();
QHBoxLayout* elementLayout = new QHBoxLayout();
elementLayout->setMargin(0);
elementWidget->setLayout(elementLayout);
QCheckBox* checkbox = new QCheckBox(elementNames[i]);
checkbox->setStyleSheet("font-size: 11pt;");
m_buttonGroup->addButton(checkbox);
elementLayout->addWidget(checkbox);
elementLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
QLabel* countLabel = new QLabel(QString::number(elementCounts[i]));
countLabel->setStyleSheet("font-size: 11pt; background-color: #333333; border-radius: 3px; color: #94D2FF;");
elementLayout->addWidget(countLabel);
m_elementWidgets.push_back(elementWidget);
mainLayout->addWidget(elementWidget);
}
// See more / less
if (showAllLessButton)
{
m_seeAllLessLabel = new LinkLabel();
connect(m_seeAllLessLabel, &LinkLabel::clicked, this, [=]()
{
m_seeAll = !m_seeAll;
UpdateSeeMoreLess();
});
mainLayout->addWidget(m_seeAllLessLabel);
}
else
{
mainLayout->addSpacing(5);
}
}
// Separating line
QFrame* hLine = new QFrame();
hLine->setFrameShape(QFrame::HLine);
hLine->setStyleSheet("color: #666666;");
vLayout->addWidget(hLine);
UpdateCollapseState();
UpdateSeeMoreLess();
}
void FilterCategoryWidget::UpdateCollapseState()
{
if (m_collapseButton->isChecked())
{
m_collapseButton->setIcon(QIcon(":/Resources/ArrowDownLine.svg"));
m_mainWidget->hide();
}
else
{
m_collapseButton->setIcon(QIcon(":/Resources/ArrowUpLine.svg"));
m_mainWidget->show();
}
}
void FilterCategoryWidget::UpdateSeeMoreLess()
{
if (!m_seeAllLessLabel)
{
return;
}
if (m_elementWidgets.isEmpty())
{
m_seeAllLessLabel->hide();
return;
}
else
{
m_seeAllLessLabel->show();
}
if (!m_seeAll)
{
m_seeAllLessLabel->setText("See all");
}
else
{
m_seeAllLessLabel->setText("See less");
}
int showCount = m_seeAll ? m_elementWidgets.size() : m_defaultShowCount;
showCount = AZ::GetMin(showCount, m_elementWidgets.size());
for (int i = 0; i < showCount; ++i)
{
m_elementWidgets[i]->show();
}
for (int i = showCount; i < m_elementWidgets.size(); ++i)
{
m_elementWidgets[i]->hide();
}
}
QButtonGroup* FilterCategoryWidget::GetButtonGroup()
{
return m_buttonGroup;
}
GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
: QScrollArea(parent)
, m_filterProxyModel(filterProxyModel)
{
m_gemModel = m_filterProxyModel->GetSourceModel();
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
QWidget* mainWidget = new QWidget();
setWidget(mainWidget);
m_mainLayout = new QVBoxLayout();
m_mainLayout->setAlignment(Qt::AlignTop);
mainWidget->setLayout(m_mainLayout);
QLabel* filterByLabel = new QLabel("Filter by");
filterByLabel->setStyleSheet("font-size: 15pt;");
m_mainLayout->addWidget(filterByLabel);
AddGemOriginFilter();
AddTypeFilter();
AddPlatformFilter();
AddFeatureFilter();
}
void GemFilterWidget::AddGemOriginFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int originIndex = 0; originIndex < GemInfo::NumGemOrigins; ++originIndex)
{
const GemInfo::GemOrigin gemOriginToBeCounted = static_cast<GemInfo::GemOrigin>(1 << originIndex);
int gemOriginCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::GemOrigin gemOrigin = m_gemModel->GetGemOrigin(m_gemModel->index(gemIndex, 0));
// Is the gem of the given origin?
if (gemOriginToBeCounted == gemOrigin)
{
gemOriginCount++;
}
}
elementNames.push_back(GemInfo::GetGemOriginString(gemOriginToBeCounted));
elementCounts.push_back(gemOriginCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::GemOrigin gemOrigin = static_cast<GemInfo::GemOrigin>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::GemOrigins gemOrigins = m_filterProxyModel->GetGemOrigins();
if (checked)
{
gemOrigins |= gemOrigin;
}
else
{
gemOrigins &= ~gemOrigin;
}
m_filterProxyModel->SetGemOrigins(gemOrigins);
});
}
}
void GemFilterWidget::AddTypeFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int typeIndex = 0; typeIndex < GemInfo::NumTypes; ++typeIndex)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << typeIndex);
int typeGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::Types types = m_gemModel->GetTypes(m_gemModel->index(gemIndex, 0));
// Is type (Asset, Code, Tool) part of the gem?
if (types & type)
{
typeGemCount++;
}
}
elementNames.push_back(GemInfo::GetTypeString(type));
elementCounts.push_back(typeGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Types types = m_filterProxyModel->GetTypes();
if (checked)
{
types |= type;
}
else
{
types &= ~type;
}
m_filterProxyModel->SetTypes(types);
});
}
}
void GemFilterWidget::AddPlatformFilter()
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int platformIndex = 0; platformIndex < GemInfo::NumPlatforms; ++platformIndex)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << platformIndex);
int platformGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(m_gemModel->index(gemIndex, 0));
// Is platform supported?
if (platforms & platform)
{
platformGemCount++;
}
}
elementNames.push_back(GemInfo::GetPlatformString(platform));
elementCounts.push_back(platformGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Platforms platforms = m_filterProxyModel->GetPlatforms();
if (checked)
{
platforms |= platform;
}
else
{
platforms &= ~platform;
}
m_filterProxyModel->SetPlatforms(platforms);
});
}
}
void GemFilterWidget::AddFeatureFilter()
{
// Alphabetically sorted, unique features and their number of occurrences in the gem database.
QMap<QString, int> uniqueFeatureCounts;
const int numGems = m_gemModel->rowCount();
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
const QStringList features = m_gemModel->GetFeatures(m_gemModel->index(gemIndex, 0));
for (const QString& feature : features)
{
if (!uniqueFeatureCounts.contains(feature))
{
uniqueFeatureCounts.insert(feature, 1);
}
else
{
int& featureeCount = uniqueFeatureCounts[feature];
featureeCount++;
}
}
}
QVector<QString> elementNames;
QVector<int> elementCounts;
for (auto iterator = uniqueFeatureCounts.begin(); iterator != uniqueFeatureCounts.end(); iterator++)
{
elementNames.push_back(iterator.key());
elementCounts.push_back(iterator.value());
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts,
/*showAllLessButton=*/true, /*defaultShowCount=*/5);
m_mainLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const QString& feature = elementNames[i];
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
QSet<QString> features = m_filterProxyModel->GetFeatures();
if (checked)
{
features.insert(feature);
}
else
{
features.remove(feature);
}
m_filterProxyModel->SetFeatures(features);
});
}
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,79 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <LinkWidget.h>
#include <GemCatalog/GemSortFilterProxyModel.h>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
#include <QCheckBox>
#include <QVector>
#include <QPushButton>
#endif
QT_FORWARD_DECLARE_CLASS(QButtonGroup)
namespace O3DE::ProjectManager
{
class FilterCategoryWidget
: public QWidget
{
Q_OBJECT // AUTOMOC
public:
explicit FilterCategoryWidget(const QString& header,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
bool showAllLessButton = true,
int defaultShowCount = 4,
QWidget* parent = nullptr);
QButtonGroup* GetButtonGroup();
private:
void UpdateCollapseState();
void UpdateSeeMoreLess();
inline constexpr static int s_collapseButtonSize = 16;
QPushButton* m_collapseButton = nullptr;
QWidget* m_mainWidget = nullptr;
QButtonGroup* m_buttonGroup = nullptr;
QVector<QWidget*> m_elementWidgets; //! Includes checkbox and the count labl.
LinkLabel* m_seeAllLessLabel = nullptr;
int m_defaultShowCount = 0;
bool m_seeAll = false;
};
class GemFilterWidget
: public QScrollArea
{
Q_OBJECT // AUTOMOC
public:
explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
~GemFilterWidget() = default;
private:
void AddGemOriginFilter();
void AddTypeFilter();
void AddPlatformFilter();
void AddFeatureFilter();
QVBoxLayout* m_mainLayout = nullptr;
GemModel* m_gemModel = nullptr;
GemSortFilterProxyModel* m_filterProxyModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -62,6 +62,19 @@ namespace O3DE::ProjectManager
}
}
QString GemInfo::GetGemOriginString(GemOrigin origin)
{
switch (origin)
{
case O3DEFoundation:
return "Open 3D Foundation";
case Local:
return "Local";
default:
return "<Unknown Gem Origin>";
}
}
bool GemInfo::IsPlatformSupported(Platform platform) const
{
return (m_platforms & platform);
@@ -46,6 +46,15 @@ namespace O3DE::ProjectManager
Q_DECLARE_FLAGS(Types, Type)
static QString GetTypeString(Type type);
enum GemOrigin
{
O3DEFoundation = 1 << 0,
Local = 1 << 1,
NumGemOrigins = 2
};
Q_DECLARE_FLAGS(GemOrigins, GemOrigin)
static QString GetGemOriginString(GemOrigin origin);
GemInfo() = default;
GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded);
bool IsPlatformSupported(Platform platform) const;
@@ -57,6 +66,7 @@ namespace O3DE::ProjectManager
QString m_displayName;
AZ::Uuid m_uuid;
QString m_creator;
GemOrigin m_gemOrigin = Local;
bool m_isAdded = false; //! Is the gem currently added and enabled in the project?
QString m_summary;
Platforms m_platforms;
@@ -74,3 +84,4 @@ namespace O3DE::ProjectManager
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::Platforms)
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::Types)
Q_DECLARE_OPERATORS_FOR_FLAGS(O3DE::ProjectManager::GemInfo::GemOrigins)
@@ -70,8 +70,8 @@ namespace O3DE::ProjectManager
m_documentationLinkLabel->SetUrl(m_model->GetDocLink(modelIndex));
// Depending and conflicting gems
m_dependingGems->Update("Depending Gems", "The following Gems will be automatically enabled with this Gem.", m_model->GetDependingGems(modelIndex));
m_conflictingGems->Update("Conflicting Gems", "The following Gems will be automatically disabled with this Gem.", m_model->GetConflictingGems(modelIndex));
m_dependingGems->Update("Depending Gems", "The following Gems will be automatically enabled with this Gem.", m_model->GetDependingGemNames(modelIndex));
m_conflictingGems->Update("Conflicting Gems", "The following Gems will be automatically disabled with this Gem.", m_model->GetConflictingGemNames(modelIndex));
// Additional information
m_versionLabel->setText(QString("Gem Version: %1").arg(m_model->GetVersion(modelIndex)));
@@ -10,7 +10,7 @@
*
*/
#include "GemItemDelegate.h"
#include <GemCatalog/GemItemDelegate.h>
#include "GemModel.h"
#include <QEvent>
#include <QPainter>
@@ -18,9 +18,9 @@
namespace O3DE::ProjectManager
{
GemItemDelegate::GemItemDelegate(GemModel* gemModel, QObject* parent)
GemItemDelegate::GemItemDelegate(QAbstractItemModel* model, QObject* parent)
: QStyledItemDelegate(parent)
, m_gemModel(gemModel)
, m_model(model)
{
AddPlatformIcon(GemInfo::Android, ":/Android.svg");
AddPlatformIcon(GemInfo::iOS, ":/iOS.svg");
@@ -78,7 +78,7 @@ namespace O3DE::ProjectManager
}
// Gem name
const QString gemName = m_gemModel->GetName(modelIndex);
const QString gemName = GemModel::GetName(modelIndex);
QFont gemNameFont(options.font);
gemNameFont.setPixelSize(s_gemNameFontSize);
gemNameFont.setBold(true);
@@ -90,7 +90,7 @@ namespace O3DE::ProjectManager
painter->drawText(gemNameRect, Qt::TextSingleLine, gemName);
// Gem creator
const QString gemCreator = m_gemModel->GetCreator(modelIndex);
const QString gemCreator = GemModel::GetCreator(modelIndex);
QRect gemCreatorRect = GetTextRect(standardFont, gemCreator, s_fontSize);
gemCreatorRect.moveTo(contentRect.left(), contentRect.top() + gemNameRect.height());
@@ -105,7 +105,7 @@ namespace O3DE::ProjectManager
painter->setFont(standardFont);
painter->setPen(m_textColor);
const QString summary = m_gemModel->GetSummary(modelIndex);
const QString summary = GemModel::GetSummary(modelIndex);
painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary);
@@ -158,7 +158,7 @@ namespace O3DE::ProjectManager
void GemItemDelegate::DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const
{
const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(modelIndex);
const GemInfo::Platforms platforms = GemModel::GetPlatforms(modelIndex);
int startX = 0;
// Iterate and draw the platforms in the order they are defined in the enum.
@@ -188,7 +188,7 @@ namespace O3DE::ProjectManager
QPoint circleCenter;
QString buttonText;
const bool isAdded = m_gemModel->IsAdded(modelIndex);
const bool isAdded = GemModel::IsAdded(modelIndex);
if (isAdded)
{
painter->setBrush(m_buttonEnabledColor);
@@ -15,7 +15,7 @@
#if !defined(Q_MOC_RUN)
#include <QStyledItemDelegate>
#include "GemInfo.h"
#include "GemModel.h"
#include <QAbstractItemModel>
#include <QHash>
#endif
@@ -29,22 +29,13 @@ namespace O3DE::ProjectManager
Q_OBJECT // AUTOMOC
public:
explicit GemItemDelegate(GemModel* gemModel, QObject* parent = nullptr);
explicit GemItemDelegate(QAbstractItemModel* model, QObject* parent = nullptr);
~GemItemDelegate() = default;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override;
private:
void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
GemModel* m_gemModel = nullptr;
// Colors
const QColor m_textColor = QColor("#FFFFFF");
const QColor m_linkColor = QColor("#94D2FF");
@@ -71,6 +62,15 @@ namespace O3DE::ProjectManager
inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 3;
inline constexpr static qreal s_buttonFontSize = 12.0;
private:
void CalcRects(const QStyleOptionViewItem& option, const QModelIndex& modelIndex, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const;
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const;
void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
QAbstractItemModel* m_model = nullptr;
// Platform icons
void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath);
inline constexpr static int s_platformIconSize = 16;
@@ -18,17 +18,15 @@
namespace O3DE::ProjectManager
{
GemListView::GemListView(GemModel* model, QWidget *parent) :
QListView(parent)
GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent)
: QListView(parent)
{
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPalette palette;
palette.setColor(QPalette::Window, QColor("#333333"));
setPalette(palette);
setStyleSheet("background-color: #333333;");
setModel(model);
setSelectionModel(model->GetSelectionModel());
setSelectionModel(selectionModel);
setItemDelegate(new GemItemDelegate(model, this));
}
} // namespace O3DE::ProjectManager
@@ -14,7 +14,8 @@
#if !defined(Q_MOC_RUN)
#include "GemInfo.h"
#include "GemModel.h"
#include <QAbstractItemModel>
#include <QItemSelectionModel>
#include <QListView>
#endif
@@ -24,8 +25,9 @@ namespace O3DE::ProjectManager
: public QListView
{
Q_OBJECT // AUTOMOC
public:
explicit GemListView(GemModel* model, QWidget *parent = nullptr);
explicit GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent = nullptr);
~GemListView() = default;
};
} // namespace O3DE::ProjectManager
@@ -36,11 +36,11 @@ namespace O3DE::ProjectManager
const QString uuidString = gemInfo.m_uuid.ToString<AZStd::string>().c_str();
item->setData(uuidString, RoleUuid);
item->setData(gemInfo.m_creator, RoleCreator);
item->setData(gemInfo.m_gemOrigin, RoleGemOrigin);
item->setData(aznumeric_cast<int>(gemInfo.m_platforms), RolePlatforms);
item->setData(aznumeric_cast<int>(gemInfo.m_types), RoleTypes);
item->setData(gemInfo.m_summary, RoleSummary);
item->setData(gemInfo.m_isAdded, RoleIsAdded);
item->setData(gemInfo.m_directoryLink, RoleDirectoryLink);
item->setData(gemInfo.m_documentationLink, RoleDocLink);
item->setData(gemInfo.m_dependingGemUuids, RoleDependingGems);
@@ -48,12 +48,12 @@ namespace O3DE::ProjectManager
item->setData(gemInfo.m_version, RoleVersion);
item->setData(gemInfo.m_lastUpdatedDate, RoleLastUpdated);
item->setData(gemInfo.m_binarySizeInKB, RoleBinarySize);
item->setData(gemInfo.m_features, RoleFeatures);
appendRow(item);
m_uuidToNameMap[uuidString] = gemInfo.m_displayName;
const QModelIndex modelIndex = index(rowCount()-1, 0);
m_uuidToIndexMap[uuidString] = modelIndex;
}
void GemModel::Clear()
@@ -71,6 +71,11 @@ namespace O3DE::ProjectManager
return modelIndex.data(RoleCreator).toString();
}
GemInfo::GemOrigin GemModel::GetGemOrigin(const QModelIndex& modelIndex)
{
return static_cast<GemInfo::GemOrigin>(modelIndex.data(RoleGemOrigin).toInt());
}
QString GemModel::GetUuidString(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleUuid).toString();
@@ -106,42 +111,63 @@ namespace O3DE::ProjectManager
return modelIndex.data(RoleDocLink).toString();
}
AZ::Outcome<QString> GemModel::FindGemNameByUuidString(const QString& uuidString) const
QModelIndex GemModel::FindIndexByUuidString(const QString& uuidString) const
{
const auto iterator = m_uuidToNameMap.find(uuidString);
if (iterator != m_uuidToNameMap.end())
const auto iterator = m_uuidToIndexMap.find(uuidString);
if (iterator != m_uuidToIndexMap.end())
{
return AZ::Success(iterator.value());
return iterator.value();
}
return AZ::Failure();
return {};
}
QStringList GemModel::GetDependingGems(const QModelIndex& modelIndex)
void GemModel::FindGemNamesByUuidStrings(QStringList& inOutGemNames)
{
QStringList result = modelIndex.data(RoleDependingGems).toStringList();
for (QString& dependingGemString : inOutGemNames)
{
QModelIndex modelIndex = FindIndexByUuidString(dependingGemString);
if (modelIndex.isValid())
{
dependingGemString = GetName(modelIndex);
}
}
}
QStringList GemModel::GetDependingGemUuids(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleDependingGems).toStringList();
}
QStringList GemModel::GetDependingGemNames(const QModelIndex& modelIndex)
{
QStringList result = GetDependingGemUuids(modelIndex);
if (result.isEmpty())
{
return {};
}
for (QString& dependingGemString : result)
{
AZ::Outcome<QString> gemNameOutcome = FindGemNameByUuidString(dependingGemString);
if (gemNameOutcome.IsSuccess())
{
dependingGemString = gemNameOutcome.GetValue();
}
}
FindGemNamesByUuidStrings(result);
return result;
}
QStringList GemModel::GetConflictingGems(const QModelIndex& modelIndex)
QStringList GemModel::GetConflictingGemUuids(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleConflictingGems).toStringList();
}
QStringList GemModel::GetConflictingGemNames(const QModelIndex& modelIndex)
{
QStringList result = GetConflictingGemUuids(modelIndex);
if (result.isEmpty())
{
return {};
}
FindGemNamesByUuidStrings(result);
return result;
}
QString GemModel::GetVersion(const QModelIndex& modelIndex)
{
return modelIndex.data(RoleVersion).toString();
@@ -13,7 +13,6 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Outcome/Outcome.h>
#include <GemCatalog/GemInfo.h>
#include <QAbstractItemModel>
#include <QStandardItemModel>
@@ -34,11 +33,16 @@ namespace O3DE::ProjectManager
void AddGem(const GemInfo& gemInfo);
void Clear();
AZ::Outcome<QString> FindGemNameByUuidString(const QString& uuidString) const;
QStringList GetDependingGems(const QModelIndex& modelIndex);
QModelIndex FindIndexByUuidString(const QString& uuidString) const;
void FindGemNamesByUuidStrings(QStringList& inOutGemNames);
QStringList GetDependingGemUuids(const QModelIndex& modelIndex);
QStringList GetDependingGemNames(const QModelIndex& modelIndex);
QStringList GetConflictingGemUuids(const QModelIndex& modelIndex);
QStringList GetConflictingGemNames(const QModelIndex& modelIndex);
static QString GetName(const QModelIndex& modelIndex);
static QString GetCreator(const QModelIndex& modelIndex);
static GemInfo::GemOrigin GetGemOrigin(const QModelIndex& modelIndex);
static QString GetUuidString(const QModelIndex& modelIndex);
static GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex);
static GemInfo::Types GetTypes(const QModelIndex& modelIndex);
@@ -46,7 +50,6 @@ namespace O3DE::ProjectManager
static bool IsAdded(const QModelIndex& modelIndex);
static QString GetDirectoryLink(const QModelIndex& modelIndex);
static QString GetDocLink(const QModelIndex& modelIndex);
static QStringList GetConflictingGems(const QModelIndex& modelIndex);
static QString GetVersion(const QModelIndex& modelIndex);
static QString GetLastUpdated(const QModelIndex& modelIndex);
static int GetBinarySizeInKB(const QModelIndex& modelIndex);
@@ -58,6 +61,7 @@ namespace O3DE::ProjectManager
RoleName = Qt::UserRole,
RoleUuid,
RoleCreator,
RoleGemOrigin,
RolePlatforms,
RoleSummary,
RoleIsAdded,
@@ -72,7 +76,7 @@ namespace O3DE::ProjectManager
RoleTypes
};
QHash<QString, QString> m_uuidToNameMap;
QHash<QString, QModelIndex> m_uuidToIndexMap;
QItemSelectionModel* m_selectionModel = nullptr;
};
} // namespace O3DE::ProjectManager
@@ -0,0 +1,133 @@
/*
* 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 <GemCatalog/GemSortFilterProxyModel.h>
#include <QItemSelectionModel>
namespace O3DE::ProjectManager
{
GemSortFilterProxyModel::GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent)
: QSortFilterProxyModel(parent)
, m_sourceModel(sourceModel)
{
setSourceModel(sourceModel);
m_selectionProxyModel = new AzQtComponents::SelectionProxyModel(sourceModel->GetSelectionModel(), this, parent);
}
bool GemSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
// Do not use sourceParent->child because an invalid parent does not produce valid children (which our index function does)
QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
if (!sourceIndex.isValid())
{
return false;
}
if (!m_sourceModel->GetName(sourceIndex).contains(m_searchString, Qt::CaseInsensitive))
{
return false;
}
// Gem origins
if (m_gemOriginFilter)
{
bool supportsAnyFilteredGemOrigin = false;
for (int i = 0; i < GemInfo::NumGemOrigins; ++i)
{
const GemInfo::GemOrigin filteredGemOrigin = static_cast<GemInfo::GemOrigin>(1 << i);
if (m_gemOriginFilter & filteredGemOrigin)
{
if ((GemModel::GetGemOrigin(sourceIndex) == filteredGemOrigin))
{
supportsAnyFilteredGemOrigin = true;
break;
}
}
}
if (!supportsAnyFilteredGemOrigin)
{
return false;
}
}
// Platform
if (m_platformFilter)
{
bool supportsAnyFilteredPlatform = false;
for (int i = 0; i < GemInfo::NumPlatforms; ++i)
{
const GemInfo::Platform filteredPlatform = static_cast<GemInfo::Platform>(1 << i);
if (m_platformFilter & filteredPlatform)
{
if ((GemModel::GetPlatforms(sourceIndex) & filteredPlatform))
{
supportsAnyFilteredPlatform = true;
break;
}
}
}
if (!supportsAnyFilteredPlatform)
{
return false;
}
}
// Types (Asset, Code, Tool)
if (m_typeFilter)
{
bool supportsAnyFilteredType = false;
for (int i = 0; i < GemInfo::NumTypes; ++i)
{
const GemInfo::Type filteredType = static_cast<GemInfo::Type>(1 << i);
if (m_typeFilter & filteredType)
{
if ((GemModel::GetTypes(sourceIndex) & filteredType))
{
supportsAnyFilteredType = true;
break;
}
}
}
if (!supportsAnyFilteredType)
{
return false;
}
}
// Features
if (!m_featureFilter.isEmpty())
{
bool containsFilterFeature = false;
const QStringList features = m_sourceModel->GetFeatures(sourceIndex);
for (const QString& feature : features)
{
if (m_featureFilter.contains(feature))
{
containsFilterFeature = true;
break;
}
}
if (!containsFilterFeature)
{
return false;
}
}
return true;
}
void GemSortFilterProxyModel::InvalidateFilter()
{
invalidate();
emit OnInvalidated();
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,68 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzQtComponents/Utilities/SelectionProxyModel.h>
#include <GemCatalog/GemModel.h>
#include <QtCore/QSortFilterProxyModel>
#include <QSet>
#endif
QT_FORWARD_DECLARE_CLASS(QItemSelectionModel)
namespace O3DE::ProjectManager
{
class GemSortFilterProxyModel
: public QSortFilterProxyModel
{
Q_OBJECT // AUTOMOC
public:
GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
GemModel* GetSourceModel() const { return m_sourceModel; }
AzQtComponents::SelectionProxyModel* GetSelectionModel() const { return m_selectionProxyModel; }
void SetSearchString(const QString& searchString) { m_searchString = searchString; InvalidateFilter(); }
GemInfo::GemOrigins GetGemOrigins() const { return m_gemOriginFilter; }
void SetGemOrigins(const GemInfo::GemOrigins& gemOrigins) { m_gemOriginFilter = gemOrigins; InvalidateFilter(); }
GemInfo::Platforms GetPlatforms() const { return m_platformFilter; }
void SetPlatforms(const GemInfo::Platforms& platforms) { m_platformFilter = platforms; InvalidateFilter(); }
GemInfo::Types GetTypes() const { return m_typeFilter; }
void SetTypes(const GemInfo::Types& types) { m_typeFilter = types; InvalidateFilter(); }
const QSet<QString>& GetFeatures() const { return m_featureFilter; }
void SetFeatures(const QSet<QString>& features) { m_featureFilter = features; InvalidateFilter(); }
void InvalidateFilter();
signals:
void OnInvalidated();
private:
GemModel* m_sourceModel = nullptr;
AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr;
QString m_searchString;
GemInfo::GemOrigins m_gemOriginFilter = {};
GemInfo::Platforms m_platformFilter = {};
GemInfo::Types m_typeFilter = {};
QSet<QString> m_featureFilter;
};
} // namespace O3DE::ProjectManager
@@ -96,11 +96,6 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::NewProjectSettings;
}
QString NewProjectSettingsScreen::GetNextButtonText()
{
return tr("Next");
}
void NewProjectSettingsScreen::HandleBrowseButton()
{
QString defaultPath = m_projectPathLineEdit->text();
@@ -28,7 +28,6 @@ namespace O3DE::ProjectManager
explicit NewProjectSettingsScreen(QWidget* parent = nullptr);
~NewProjectSettingsScreen() = default;
ProjectManagerScreen GetScreenEnum() override;
QString GetNextButtonText() override;
ProjectInfo GetProjectInfo();
QString GetProjectTemplatePath();
@@ -0,0 +1,102 @@
/*
* 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 <ProjectButtonWidget.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QResizeEvent>
#include <QLabel>
#include <QPushButton>
#include <QPixmap>
#include <QMenu>
#include <QSpacerItem>
//#define SHOW_ALL_PROJECT_ACTIONS
namespace O3DE::ProjectManager
{
inline constexpr static int s_projectImageWidth = 210;
inline constexpr static int s_projectImageHeight = 280;
LabelButton::LabelButton(QWidget* parent)
: QLabel(parent)
{
}
void LabelButton::mousePressEvent([[maybe_unused]] QMouseEvent* event)
{
emit triggered();
}
ProjectButton::ProjectButton(const QString& projectName, QWidget* parent)
: QFrame(parent)
, m_projectName(projectName)
, m_projectImagePath(":/Resources/DefaultProjectImage.png")
{
Setup();
}
ProjectButton::ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent)
: QFrame(parent)
, m_projectName(projectName)
, m_projectImagePath(projectImage)
{
Setup();
}
void ProjectButton::Setup()
{
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setSpacing(0);
vLayout->setContentsMargins(0, 0, 0, 0);
setLayout(vLayout);
m_projectImageLabel = new LabelButton(this);
m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight);
vLayout->addWidget(m_projectImageLabel);
m_projectImageLabel->setPixmap(QPixmap(m_projectImagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
QMenu* newProjectMenu = new QMenu(this);
m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings..."));
#ifdef SHOW_ALL_PROJECT_ACTIONS
m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
newProjectMenu->addSeparator();
m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate"));
newProjectMenu->addSeparator();
m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE"));
m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project"));
#endif
m_projectSettingsMenuButton = new QPushButton(this);
m_projectSettingsMenuButton->setText(m_projectName);
m_projectSettingsMenuButton->setMenu(newProjectMenu);
m_projectSettingsMenuButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
m_projectSettingsMenuButton->setStyleSheet("font-size: 14px; text-align:left;");
vLayout->addWidget(m_projectSettingsMenuButton);
setFixedSize(s_projectImageWidth, s_projectImageHeight + m_projectSettingsMenuButton->height());
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); });
connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); });
#ifdef SHOW_ALL_PROJECT_ACTIONS
connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectName); });
connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectName); });
connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectName); });
connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectName); });
#endif
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,73 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QFrame>
#include <QLabel>
#endif
QT_FORWARD_DECLARE_CLASS(QPixmap)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QAction)
namespace O3DE::ProjectManager
{
class LabelButton
: public QLabel
{
Q_OBJECT // AUTOMOC
public:
explicit LabelButton(QWidget* parent = nullptr);
~LabelButton() = default;
signals:
void triggered();
public slots:
void mousePressEvent(QMouseEvent* event) override;
};
class ProjectButton
: public QFrame
{
Q_OBJECT // AUTOMOC
public:
explicit ProjectButton(const QString& projectName, QWidget* parent = nullptr);
explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr);
~ProjectButton() = default;
signals:
void OpenProject(const QString& projectName);
void EditProject(const QString& projectName);
void EditProjectGems(const QString& projectName);
void CopyProject(const QString& projectName);
void RemoveProject(const QString& projectName);
void DeleteProject(const QString& projectName);
private:
void Setup();
QString m_projectName;
QString m_projectImagePath;
LabelButton* m_projectImageLabel;
QPushButton* m_projectSettingsMenuButton;
QAction* m_editProjectAction;
QAction* m_editProjectGemsAction;
QAction* m_copyProjectAction;
QAction* m_removeProjectAction;
QAction* m_deleteProjectAction;
};
} // namespace O3DE::ProjectManager
@@ -32,8 +32,6 @@ namespace O3DE::ProjectManager
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
setFixedSize(this->geometry().width(), this->geometry().height());
m_pythonBindings = AZStd::make_unique<PythonBindings>(engineRootPath);
m_screensCtrl = new ScreensCtrl();
@@ -52,9 +50,9 @@ namespace O3DE::ProjectManager
QVector<ProjectManagerScreen> screenEnums =
{
ProjectManagerScreen::FirstTimeUse,
ProjectManagerScreen::NewProjectSettingsCore,
ProjectManagerScreen::CreateProject,
ProjectManagerScreen::ProjectsHome,
ProjectManagerScreen::ProjectSettings,
ProjectManagerScreen::UpdateProject,
ProjectManagerScreen::EngineSettings
};
m_screensCtrl->BuildScreens(screenEnums);
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -30,6 +30,23 @@ namespace O3DE::ProjectManager
return ProjectManagerScreen::ProjectSettings;
}
ProjectInfo ProjectSettingsScreen::GetProjectInfo()
{
// Impl pending next PR
return ProjectInfo();
}
void ProjectSettingsScreen::SetProjectInfo()
{
// Impl pending next PR
}
bool ProjectSettingsScreen::Validate()
{
// Impl pending next PR
return true;
}
void ProjectSettingsScreen::HandleGemsButton()
{
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
@@ -13,6 +13,7 @@
#if !defined(Q_MOC_RUN)
#include <ScreenWidget.h>
#include <ProjectInfo.h>
#endif
namespace Ui
@@ -30,6 +31,11 @@ namespace O3DE::ProjectManager
~ProjectSettingsScreen() = default;
ProjectManagerScreen GetScreenEnum() override;
ProjectInfo GetProjectInfo();
void SetProjectInfo();
bool Validate();
protected slots:
void HandleGemsButton();
@@ -12,21 +12,103 @@
#include <ProjectsHomeScreen.h>
#include <Source/ui_ProjectsHomeScreen.h>
#include <ProjectButtonWidget.h>
#include <PythonBindingsInterface.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QMenu>
#include <QListView>
#include <QSpacerItem>
#include <QListWidget>
#include <QListWidgetItem>
#include <QFileInfo>
#include <QScrollArea>
namespace O3DE::ProjectManager
{
ProjectsHomeScreen::ProjectsHomeScreen(QWidget* parent)
: ScreenWidget(parent)
, m_ui(new Ui::ProjectsHomeClass())
{
m_ui->setupUi(this);
QVBoxLayout* vLayout = new QVBoxLayout();
setLayout(vLayout);
vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins);
connect(m_ui->newProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleNewProjectButton);
connect(m_ui->addProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleAddProjectButton);
connect(m_ui->editProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleEditProjectButton);
QHBoxLayout* topLayout = new QHBoxLayout();
QLabel* titleLabel = new QLabel(this);
titleLabel->setText("My Projects");
titleLabel->setStyleSheet("font-size: 24px");
topLayout->addWidget(titleLabel);
QSpacerItem* topSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum);
topLayout->addItem(topSpacer);
QMenu* newProjectMenu = new QMenu(this);
m_createNewProjectAction = newProjectMenu->addAction("Create New Project");
m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project");
QPushButton* newProjectMenuButton = new QPushButton(this);
newProjectMenuButton->setText("New Project...");
newProjectMenuButton->setMenu(newProjectMenu);
newProjectMenuButton->setFixedWidth(s_newProjectButtonWidth);
newProjectMenuButton->setStyleSheet("font-size: 14px;");
topLayout->addWidget(newProjectMenuButton);
vLayout->addLayout(topLayout);
// Get all projects and create a horizontal scrolling list of them
auto projectsResult = PythonBindingsInterface::Get()->GetProjects();
if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty())
{
QScrollArea* projectsScrollArea = new QScrollArea(this);
QWidget* scrollWidget = new QWidget();
QGridLayout* projectGridLayout = new QGridLayout();
scrollWidget->setLayout(projectGridLayout);
projectsScrollArea->setWidget(scrollWidget);
projectsScrollArea->setWidgetResizable(true);
int gridIndex = 0;
for (auto project : projectsResult.GetValue())
{
ProjectButton* projectButton;
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
QFileInfo doesPreviewExist(projectPreviewPath);
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
{
projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
}
else
{
projectButton = new ProjectButton(project.m_projectName, this);
}
// Create rows of projects buttons s_projectButtonRowCount buttons wide
projectGridLayout->addWidget(projectButton, gridIndex / s_projectButtonRowCount, gridIndex % s_projectButtonRowCount);
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsHomeScreen::HandleOpenProject);
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsHomeScreen::HandleEditProject);
#ifdef SHOW_ALL_PROJECT_ACTIONS
connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsHomeScreen::HandleEditProjectGems);
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsHomeScreen::HandleCopyProject);
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsHomeScreen::HandleRemoveProject);
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsHomeScreen::HandleDeleteProject);
#endif
++gridIndex;
}
vLayout->addWidget(projectsScrollArea);
}
// Using border-image allows for scaling options background-image does not support
setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }");
connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleNewProjectButton);
connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleAddProjectButton);
}
ProjectManagerScreen ProjectsHomeScreen::GetScreenEnum()
@@ -36,16 +118,41 @@ namespace O3DE::ProjectManager
void ProjectsHomeScreen::HandleNewProjectButton()
{
emit ResetScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
emit ChangeScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
}
void ProjectsHomeScreen::HandleAddProjectButton()
{
// Do nothing for now
}
void ProjectsHomeScreen::HandleEditProjectButton()
void ProjectsHomeScreen::HandleOpenProject(const QString& projectPath)
{
emit ChangeScreenRequest(ProjectManagerScreen::ProjectSettings);
// Open the editor with this project open
emit NotifyCurrentProject(projectPath);
}
void ProjectsHomeScreen::HandleEditProject(const QString& projectPath)
{
emit NotifyCurrentProject(projectPath);
emit ResetScreenRequest(ProjectManagerScreen::UpdateProject);
emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject);
}
void ProjectsHomeScreen::HandleEditProjectGems(const QString& projectPath)
{
emit NotifyCurrentProject(projectPath);
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
}
void ProjectsHomeScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
{
// Open file dialog and choose location for copied project then register copy with O3DE
}
void ProjectsHomeScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
{
// Unregister Project from O3DE
}
void ProjectsHomeScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
{
// Remove project from 03DE and delete from disk
ProjectsHomeScreen::HandleRemoveProject(projectPath);
}
} // namespace O3DE::ProjectManager
@@ -15,11 +15,6 @@
#include <ScreenWidget.h>
#endif
namespace Ui
{
class ProjectsHomeClass;
}
namespace O3DE::ProjectManager
{
class ProjectsHomeScreen
@@ -34,10 +29,23 @@ namespace O3DE::ProjectManager
protected slots:
void HandleNewProjectButton();
void HandleAddProjectButton();
void HandleEditProjectButton();
void HandleOpenProject(const QString& projectPath);
void HandleEditProject(const QString& projectPath);
void HandleEditProjectGems(const QString& projectPath);
void HandleCopyProject(const QString& projectPath);
void HandleRemoveProject(const QString& projectPath);
void HandleDeleteProject(const QString& projectPath);
private:
QScopedPointer<Ui::ProjectsHomeClass> m_ui;
QAction* m_createNewProjectAction;
QAction* m_addExistingProjectAction;
const QString m_projectPreviewImagePath = "/preview.png";
inline constexpr static int s_contentMargins = 80;
inline constexpr static int s_spacerSize = 20;
inline constexpr static int s_projectButtonRowCount = 4;
inline constexpr static int s_newProjectButtonWidth = 156;
};
} // namespace O3DE::ProjectManager
@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectsHomeClass</class>
<widget class="QWidget" name="ProjectsHomeClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>826</width>
<height>585</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>My Projects</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="currentProjectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="newProjectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources/ProjectManager.qrc">
<normaloff>:/Add.svg</normaloff>:/Add.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addProjectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources/ProjectManager.qrc">
<normaloff>:/Select_Folder.svg</normaloff>:/Select_Folder.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QToolButton" name="editProjectButton">
<property name="text">
<string>Edit Project</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Open a Project</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>
<include location="../Resources/ProjectManager.qrc"/>
</resources>
<connections/>
</ui>
@@ -540,7 +540,8 @@ namespace O3DE::ProjectManager
ProjectInfo PythonBindings::ProjectInfoFromPath(pybind11::handle path)
{
ProjectInfo projectInfo;
projectInfo.m_path = Py_To_String(path);
projectInfo.m_path = Py_To_String(path);
projectInfo.m_isNew = false;
auto projectData = m_registration.attr("get_project_data")(pybind11::none(), path);
if (pybind11::isinstance<pybind11::dict>(projectData))
@@ -18,10 +18,11 @@ namespace O3DE::ProjectManager
Invalid = -1,
Empty,
FirstTimeUse,
NewProjectSettingsCore,
CreateProject,
NewProjectSettings,
GemCatalog,
ProjectsHome,
UpdateProject,
ProjectSettings,
EngineSettings
};
@@ -12,7 +12,8 @@
#include <ScreenFactory.h>
#include <FirstTimeUseScreen.h>
#include <ProjectSettingsCtrl.h>
#include <CreateProjectCtrl.h>
#include <UpdateProjectCtrl.h>
#include <NewProjectSettingsScreen.h>
#include <GemCatalog/GemCatalogScreen.h>
#include <ProjectsHomeScreen.h>
@@ -30,8 +31,8 @@ namespace O3DE::ProjectManager
case (ProjectManagerScreen::FirstTimeUse):
newScreen = new FirstTimeUseScreen(parent);
break;
case (ProjectManagerScreen::NewProjectSettingsCore):
newScreen = new ProjectSettingsCtrl(parent);
case (ProjectManagerScreen::CreateProject):
newScreen = new CreateProjectCtrl(parent);
break;
case (ProjectManagerScreen::NewProjectSettings):
newScreen = new NewProjectSettingsScreen(parent);
@@ -42,6 +43,9 @@ namespace O3DE::ProjectManager
case (ProjectManagerScreen::ProjectsHome):
newScreen = new ProjectsHomeScreen(parent);
break;
case (ProjectManagerScreen::UpdateProject):
newScreen = new UpdateProjectCtrl(parent);
break;
case (ProjectManagerScreen::ProjectSettings):
newScreen = new ProjectSettingsScreen(parent);
break;
@@ -41,15 +41,12 @@ namespace O3DE::ProjectManager
{
return true;
}
virtual QString GetNextButtonText()
{
return "Next";
}
signals:
void ChangeScreenRequest(ProjectManagerScreen screen);
void GotoPreviousScreenRequest();
void ResetScreenRequest(ProjectManagerScreen screen);
void NotifyCurrentProject(const QString& projectPath);
};
} // namespace O3DE::ProjectManager
@@ -117,6 +117,7 @@ namespace O3DE::ProjectManager
connect(newScreen, &ScreenWidget::ChangeScreenRequest, this, &ScreensCtrl::ChangeToScreen);
connect(newScreen, &ScreenWidget::GotoPreviousScreenRequest, this, &ScreensCtrl::GotoPreviousScreen);
connect(newScreen, &ScreenWidget::ResetScreenRequest, this, &ScreensCtrl::ResetScreen);
connect(newScreen, &ScreenWidget::NotifyCurrentProject, this, &ScreensCtrl::NotifyCurrentProject);
}
void ScreensCtrl::ResetAllScreens()
@@ -35,6 +35,9 @@ namespace O3DE::ProjectManager
ScreenWidget* FindScreen(ProjectManagerScreen screen);
ScreenWidget* GetCurrentScreen();
signals:
void NotifyCurrentProject(const QString& projectPath);
public slots:
bool ChangeToScreen(ProjectManagerScreen screen);
bool ForceChangeToScreen(ProjectManagerScreen screen, bool addVisit = true);
@@ -0,0 +1,139 @@
/*
* 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 <UpdateProjectCtrl.h>
#include <ScreensCtrl.h>
#include <PythonBindingsInterface.h>
#include <ProjectSettingsScreen.h>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QPushButton>
#include <QMessageBox>
namespace O3DE::ProjectManager
{
UpdateProjectCtrl::UpdateProjectCtrl(QWidget* parent)
: ScreenWidget(parent)
{
QVBoxLayout* vLayout = new QVBoxLayout();
setLayout(vLayout);
m_screensCtrl = new ScreensCtrl();
vLayout->addWidget(m_screensCtrl);
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
vLayout->addWidget(backNextButtons);
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
connect(m_backButton, &QPushButton::pressed, this, &UpdateProjectCtrl::HandleBackButton);
connect(m_nextButton, &QPushButton::pressed, this, &UpdateProjectCtrl::HandleNextButton);
connect(reinterpret_cast<ScreensCtrl*>(parent), &ScreensCtrl::NotifyCurrentProject, this, &UpdateProjectCtrl::UpdateCurrentProject);
m_screensOrder =
{
ProjectManagerScreen::ProjectSettings,
ProjectManagerScreen::GemCatalog
};
m_screensCtrl->BuildScreens(m_screensOrder);
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::ProjectSettings, false);
UpdateNextButtonText();
}
ProjectManagerScreen UpdateProjectCtrl::GetScreenEnum()
{
return ProjectManagerScreen::UpdateProject;
}
void UpdateProjectCtrl::HandleBackButton()
{
if (!m_screensCtrl->GotoPreviousScreen())
{
emit GotoPreviousScreenRequest();
}
else
{
UpdateNextButtonText();
}
}
void UpdateProjectCtrl::HandleNextButton()
{
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
auto screenOrderIter = m_screensOrder.begin();
for (; screenOrderIter != m_screensOrder.end(); ++screenOrderIter)
{
if (*screenOrderIter == screenEnum)
{
++screenOrderIter;
break;
}
}
if (screenEnum == ProjectManagerScreen::ProjectSettings)
{
auto projectScreen = reinterpret_cast<ProjectSettingsScreen*>(currentScreen);
if (projectScreen)
{
if (!projectScreen->Validate())
{
QMessageBox::critical(this, tr("Invalid project settings"), tr("Invalid project settings"));
return;
}
m_projectInfo = projectScreen->GetProjectInfo();
}
}
if (screenOrderIter != m_screensOrder.end())
{
m_screensCtrl->ChangeToScreen(*screenOrderIter);
UpdateNextButtonText();
}
else
{
auto result = PythonBindingsInterface::Get()->UpdateProject(m_projectInfo);
if (result)
{
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
}
else
{
QMessageBox::critical(this, tr("Project update failed"), tr("Failed to update project."));
}
}
}
void UpdateProjectCtrl::UpdateCurrentProject(const QString& projectPath)
{
auto projectResult = PythonBindingsInterface::Get()->GetProject(projectPath);
if (projectResult.IsSuccess())
{
m_projectInfo = projectResult.GetValue();
}
}
void UpdateProjectCtrl::UpdateNextButtonText()
{
QString nextButtonText = tr("Continue");
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
{
nextButtonText = tr("Update Project");
}
m_nextButton->setText(nextButtonText);
}
} // namespace O3DE::ProjectManager
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include "ProjectInfo.h"
#include <ScreenWidget.h>
#include <ScreensCtrl.h>
#include <QPushButton>
#endif
namespace O3DE::ProjectManager
{
class UpdateProjectCtrl
: public ScreenWidget
{
public:
explicit UpdateProjectCtrl(QWidget* parent = nullptr);
~UpdateProjectCtrl() = default;
ProjectManagerScreen GetScreenEnum() override;
protected slots:
void HandleBackButton();
void HandleNextButton();
void UpdateCurrentProject(const QString& projectPath);
private:
void UpdateNextButtonText();
ScreensCtrl* m_screensCtrl;
QPushButton* m_backButton;
QPushButton* m_nextButton;
QVector<ProjectManagerScreen> m_screensOrder;
ProjectInfo m_projectInfo;
ProjectManagerScreen m_screenEnum;
};
} // namespace O3DE::ProjectManager
@@ -41,22 +41,27 @@ set(FILES
Source/ProjectInfo.cpp
Source/NewProjectSettingsScreen.h
Source/NewProjectSettingsScreen.cpp
Source/ProjectSettingsCtrl.h
Source/ProjectSettingsCtrl.cpp
Source/CreateProjectCtrl.h
Source/CreateProjectCtrl.cpp
Source/UpdateProjectCtrl.h
Source/UpdateProjectCtrl.cpp
Source/ProjectsHomeScreen.h
Source/ProjectsHomeScreen.cpp
Source/ProjectsHomeScreen.ui
Source/ProjectSettingsScreen.h
Source/ProjectSettingsScreen.cpp
Source/ProjectSettingsScreen.ui
Source/EngineSettingsScreen.h
Source/EngineSettingsScreen.cpp
Source/ProjectButtonWidget.h
Source/ProjectButtonWidget.cpp
Source/LinkWidget.h
Source/LinkWidget.cpp
Source/TagWidget.h
Source/TagWidget.cpp
Source/GemCatalog/GemCatalogScreen.h
Source/GemCatalog/GemCatalogScreen.cpp
Source/GemCatalog/GemFilterWidget.h
Source/GemCatalog/GemFilterWidget.cpp
Source/GemCatalog/GemInfo.h
Source/GemCatalog/GemInfo.cpp
Source/GemCatalog/GemInspector.h
@@ -67,4 +72,6 @@ set(FILES
Source/GemCatalog/GemListView.cpp
Source/GemCatalog/GemModel.h
Source/GemCatalog/GemModel.cpp
Source/GemCatalog/GemSortFilterProxyModel.h
Source/GemCatalog/GemSortFilterProxyModel.cpp
)
@@ -41,6 +41,18 @@ namespace AZ
static AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler* g_fbxImporter = nullptr;
static AZStd::vector<AZ::ComponentDescriptor*> g_componentDescriptors;
void Initialize()
{
// Currently it's still needed to explicitly create an instance of this instead of letting
// it be a normal component. This is because ResourceCompilerScene needs to return
// the list of available extensions before it can start the application.
if (!g_fbxImporter)
{
g_fbxImporter = aznew AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler();
g_fbxImporter->Activate();
}
}
void Reflect(AZ::SerializeContext* /*context*/)
{
// Descriptor registration is done in Reflect instead of Initialize because the ResourceCompilerScene initializes the libraries before
@@ -52,7 +64,6 @@ namespace AZ
{
// Global importer and behavior
g_componentDescriptors.push_back(FbxSceneBuilder::FbxImporter::CreateDescriptor());
g_componentDescriptors.push_back(FbxSceneImporter::FbxImportRequestHandler::CreateDescriptor());
// Node and attribute importers
g_componentDescriptors.push_back(AssImpBitangentStreamImporter::CreateDescriptor());
@@ -114,11 +125,7 @@ namespace AZ
extern "C" AZ_DLL_EXPORT void InitializeDynamicModule(void* env)
{
AZ::Environment::Attach(static_cast<AZ::EnvironmentInstance>(env));
if (!AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter)
{
AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter = aznew AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler();
AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter->Activate();
}
AZ::SceneAPI::FbxSceneBuilder::Initialize();
}
extern "C" AZ_DLL_EXPORT void Reflect(AZ::SerializeContext* context)
{
@@ -10,16 +10,12 @@
*
*/
#include <AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Containers/Scene.h>
#include <SceneAPI/SceneCore/Events/CallProcessorBus.h>
#include <SceneAPI/SceneCore/Events/ImportEventContext.h>
#include <SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.h>
namespace AZ
{
@@ -27,23 +23,10 @@ namespace AZ
{
namespace FbxSceneImporter
{
void SceneImporterSettings::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext)
{
serializeContext->Class<SceneImporterSettings>()
->Version(1)
->Field("SupportedFileTypeExtensions", &SceneImporterSettings::m_supportedFileTypeExtensions);
}
}
const char* FbxImportRequestHandler::s_extension = ".fbx";
void FbxImportRequestHandler::Activate()
{
if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
{
settingsRegistry->GetObject(m_settings, "/O3DE/SceneAPI/AssetImporter");
}
BusConnect();
}
@@ -54,38 +37,21 @@ namespace AZ
void FbxImportRequestHandler::Reflect(ReflectContext* context)
{
SceneImporterSettings::Reflect(context);
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<FbxImportRequestHandler, AZ::Component>()->Version(1)->Attribute(
AZ::Edit::Attributes::SystemComponentTags,
AZStd::vector<AZ::Crc32>({AssetBuilderSDK::ComponentTags::AssetBuilder}));
serializeContext->Class<FbxImportRequestHandler, SceneCore::BehaviorComponent>()->Version(1);
}
}
void FbxImportRequestHandler::GetSupportedFileExtensions(AZStd::unordered_set<AZStd::string>& extensions)
{
// It's unlikely an empty file extension list is intentional,
// so if it's empty, try reloading it from the registry.
if (m_settings.m_supportedFileTypeExtensions.empty())
{
if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
{
settingsRegistry->GetObject(m_settings, "/O3DE/SceneAPI/AssetImporter");
}
}
extensions.insert(m_settings.m_supportedFileTypeExtensions.begin(), m_settings.m_supportedFileTypeExtensions.end());
extensions.insert(s_extension);
}
Events::LoadingResult FbxImportRequestHandler::LoadAsset(Containers::Scene& scene, const AZStd::string& path, const Uuid& guid, [[maybe_unused]] RequestingApplication requester)
{
AZStd::string extension;
StringFunc::Path::GetExtension(path.c_str(), extension);
if (!m_settings.m_supportedFileTypeExtensions.contains(extension))
if (!AzFramework::StringFunc::Path::IsExtension(path.c_str(), s_extension))
{
return Events::LoadingResult::Ignored;
}
@@ -107,11 +73,6 @@ namespace AZ
return Events::LoadingResult::AssetFailure;
}
}
void FbxImportRequestHandler::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
{
provided.emplace_back(AZ_CRC_CE("AssetImportRequestHandler"));
}
} // namespace Import
} // namespace SceneAPI
} // namespace AZ
@@ -21,21 +21,12 @@ namespace AZ
{
namespace FbxSceneImporter
{
struct SceneImporterSettings
{
AZ_TYPE_INFO(SceneImporterSettings, "{8BB6C7AD-BF99-44DC-9DA1-E7AD3F03DC10}");
static void Reflect(AZ::ReflectContext* context);
AZStd::unordered_set<AZStd::string> m_supportedFileTypeExtensions;
};
class FbxImportRequestHandler
: public AZ::Component
: public SceneCore::BehaviorComponent
, public Events::AssetImportRequestBus::Handler
{
public:
AZ_COMPONENT(FbxImportRequestHandler, "{9F4B189C-0A96-4F44-A5F0-E087FF1561F8}");
AZ_COMPONENT(FbxImportRequestHandler, "{9F4B189C-0A96-4F44-A5F0-E087FF1561F8}", SceneCore::BehaviorComponent);
~FbxImportRequestHandler() override = default;
@@ -47,13 +38,8 @@ namespace AZ
Events::LoadingResult LoadAsset(Containers::Scene& scene, const AZStd::string& path, const Uuid& guid,
RequestingApplication requester) override;
static void GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided);
private:
SceneImporterSettings m_settings;
static constexpr const char* SettingsFilename = "AssetImporterSettings.json";
static const char* s_extension;
};
} // namespace FbxSceneImporter
} // namespace SceneAPI
@@ -51,6 +51,25 @@ namespace AZ
float m_maxY = 0.0f;
float m_minZ = 0.0f;
float m_maxZ = 1.0f;
float GetWidth() const;
float GetHeight() const;
float GetDepth() const;
};
} // namespace RHI
} // namespace AZ
inline float AZ::RHI::Viewport::GetWidth() const
{
return m_maxX - m_minX;
}
inline float AZ::RHI::Viewport::GetHeight() const
{
return m_maxY - m_minY;
}
inline float AZ::RHI::Viewport::GetDepth() const
{
return m_maxZ - m_minZ;
}
@@ -12,17 +12,16 @@
#pragma once
#include <ModernViewportCameraControllerRequestBus.h>
#include <Atom/RPI.Public/ViewportContext.h>
#include <AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Viewport/CameraInput.h>
#include <AzFramework/Viewport/MultiViewportController.h>
namespace SandboxEditor
namespace AtomToolsFramework
{
class ModernViewportCameraControllerInstance;
class ModernViewportCameraController
class ModularViewportCameraController
: public AzFramework::MultiViewportController<
ModernViewportCameraControllerInstance, AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
{
@@ -39,19 +38,19 @@ namespace SandboxEditor
};
class ModernViewportCameraControllerInstance final
: public AzFramework::MultiViewportControllerInstanceInterface<ModernViewportCameraController>,
public ModernViewportCameraControllerRequestBus::Handler,
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>,
public ModularViewportCameraControllerRequestBus::Handler,
private AzFramework::ViewportDebugDisplayEventBus::Handler
{
public:
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModernViewportCameraController* controller);
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
~ModernViewportCameraControllerInstance() override;
// MultiViewportControllerInstanceInterface overrides ...
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
// ModernViewportCameraControllerRequestBus overrides ...
// ModularViewportCameraControllerRequestBus overrides ...
void InterpolateToTransform(const AZ::Transform& worldFromLocal) override;
private:
@@ -76,4 +75,4 @@ namespace SandboxEditor
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
};
} // namespace SandboxEditor
} // namespace AtomToolsFramework
@@ -20,11 +20,11 @@ namespace AZ
class Transform;
}
namespace SandboxEditor
namespace AtomToolsFramework
{
//! Provides an interface to control the modern viewport camera controller from the Editor.
//! @note The bus is addressed by viewport id.
class ModernViewportCameraControllerRequests : public AZ::EBusTraits
class ModularViewportCameraControllerRequests : public AZ::EBusTraits
{
public:
using BusIdType = AzFramework::ViewportId;
@@ -35,8 +35,8 @@ namespace SandboxEditor
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0;
protected:
~ModernViewportCameraControllerRequests() = default;
~ModularViewportCameraControllerRequests() = default;
};
using ModernViewportCameraControllerRequestBus = AZ::EBus<ModernViewportCameraControllerRequests>;
} // namespace SandboxEditor
using ModularViewportCameraControllerRequestBus = AZ::EBus<ModularViewportCameraControllerRequests>;
} // namespace AtomToolsFramework
@@ -10,10 +10,9 @@
*
*/
#include "ModernViewportCameraController.h"
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
@@ -23,7 +22,7 @@
#include <AzFramework/Windowing/WindowBus.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
namespace SandboxEditor
namespace AtomToolsFramework
{
// debug
void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength)
@@ -53,12 +52,12 @@ namespace SandboxEditor
return viewportContext;
}
void ModernViewportCameraController::SetCameraListBuilderCallback(const CameraListBuilder& builder)
void ModularViewportCameraController::SetCameraListBuilderCallback(const CameraListBuilder& builder)
{
m_cameraListBuilder = builder;
}
void ModernViewportCameraController::SetupCameras(AzFramework::Cameras& cameras)
void ModularViewportCameraController::SetupCameras(AzFramework::Cameras& cameras)
{
if (m_cameraListBuilder)
{
@@ -67,8 +66,8 @@ namespace SandboxEditor
}
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(
const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller)
: MultiViewportControllerInstanceInterface<ModernViewportCameraController>(viewportId, controller)
const AzFramework::ViewportId viewportId, ModularViewportCameraController* controller)
: MultiViewportControllerInstanceInterface<ModularViewportCameraController>(viewportId, controller)
{
controller->SetupCameras(m_cameraSystem.m_cameras);
@@ -88,12 +87,12 @@ namespace SandboxEditor
}
AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
ModernViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
ModularViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
}
ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance()
{
ModernViewportCameraControllerRequestBus::Handler::BusDisconnect();
ModularViewportCameraControllerRequestBus::Handler::BusDisconnect();
AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
}
@@ -182,4 +181,4 @@ namespace SandboxEditor
m_transformStart = m_camera.Transform();
m_transformEnd = worldFromLocal;
}
} // namespace SandboxEditor
} // namespace AtomToolsFramework
@@ -24,6 +24,8 @@ set(FILES
Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
Include/AtomToolsFramework/Util/Util.h
Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h
Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
Source/Communication/LocalServer.cpp
Source/Communication/LocalSocket.cpp
Source/Debug/TraceRecorder.cpp
@@ -38,4 +40,5 @@ set(FILES
Source/Util/MaterialPropertyUtil.cpp
Source/Util/Util.cpp
Source/Viewport/RenderViewportWidget.cpp
Source/Viewport/ModularViewportCameraController.cpp
)
@@ -47,6 +47,9 @@ namespace MaterialEditor
//! @param distanceMax furthest camera can be from the target
virtual void GetExtents(float& distanceMin, float& distanceMax) const = 0;
//! Get bounding sphere radius of the active model
virtual float GetRadius() const = 0;
//! Reset camera to default position and rotation
virtual void Reset() = 0;
@@ -44,6 +44,8 @@ namespace MaterialEditor
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_targetPosition,
&MaterialEditorViewportInputControllerRequestBus::Handler::GetTargetPosition);
MaterialEditorViewportInputControllerRequestBus::BroadcastResult(
m_radius, &MaterialEditorViewportInputControllerRequestBus::Handler::GetRadius);
}
void Behavior::End()
@@ -119,7 +121,8 @@ namespace MaterialEditor
float Behavior::GetSensitivityZ()
{
return 0.001f;
// adjust zooming sensitivity by model size, so that large models zoom at the same speed as smaller ones
return 0.001f * AZ::GetMax(0.5f, m_radius);
}
AZ::Quaternion Behavior::LookRotation(AZ::Vector3 forward)
@@ -54,6 +54,8 @@ namespace MaterialEditor
float m_y = 0;
//! delta scroll wheel accumulated during current frame
float m_z = 0;
//! Model radius
float m_radius = 1.0f;
AZ::EntityId m_cameraEntityId;
AZ::Vector3 m_targetPosition = AZ::Vector3::CreateZero();
@@ -114,6 +114,11 @@ namespace MaterialEditor
distanceMax = m_distanceMax;
}
float MaterialEditorViewportInputController::GetRadius() const
{
return m_radius;
}
void MaterialEditorViewportInputController::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
if (m_keysChanged)
@@ -306,11 +311,10 @@ namespace MaterialEditor
if (modelAsset.IsReady())
{
const AZ::Aabb& aabb = modelAsset->GetAabb();
float radius;
aabb.GetAsSphere(m_modelCenter, radius);
aabb.GetAsSphere(m_modelCenter, m_radius);
m_distanceMin = 0.5f * AZ::GetMin(AZ::GetMin(aabb.GetExtents().GetX(), aabb.GetExtents().GetY()), aabb.GetExtents().GetZ()) + DepthNear;
m_distanceMax = radius * MaxDistanceMultiplier;
m_distanceMax = m_radius * MaxDistanceMultiplier;
}
}
}
@@ -43,6 +43,7 @@ namespace MaterialEditor
void SetTargetPosition(const AZ::Vector3& targetPosition) override;
float GetDistanceToTarget() const override;
void GetExtents(float& distanceMin, float& distanceMax) const override;
float GetRadius() const override;
void Reset() override;
void SetFieldOfView(float value) override;
bool IsCameraCentered() const override;
@@ -96,6 +97,8 @@ namespace MaterialEditor
float m_distanceMin = 1.0f;
//! Maximum distance from camera to target
float m_distanceMax = 10.0f;
//! Model radius
float m_radius = 1.0f;
//! True if camera is centered on a model
bool m_isCameraCentered = true;
@@ -576,6 +576,29 @@ namespace AZ::AtomBridge
}
}
void AtomDebugDisplayViewportInterface::DrawWireOBB(
const AZ::Vector3& center,
const AZ::Vector3& axisX,
const AZ::Vector3& axisY,
const AZ::Vector3& axisZ,
const AZ::Vector3& halfExtents)
{
if (m_auxGeomPtr)
{
AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ));
AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents);
m_auxGeomPtr->DrawObb(
obb,
AZ::Vector3::CreateZero(),
m_rendState.m_color,
AZ::RPI::AuxGeomDraw::DrawStyle::Line,
m_rendState.m_depthTest,
m_rendState.m_depthWrite,
m_rendState.m_faceCullMode,
m_rendState.m_viewProjOverrideIndex);
}
}
void AtomDebugDisplayViewportInterface::DrawSolidOBB(
const AZ::Vector3& center,
const AZ::Vector3& axisX,
@@ -906,7 +929,28 @@ namespace AZ::AtomBridge
}
}
void AtomDebugDisplayViewportInterface::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded)
void AtomDebugDisplayViewportInterface::DrawWireCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height)
{
if (m_auxGeomPtr)
{
const AZ::Vector3 worldPos = ToWorldSpacePosition(pos);
const AZ::Vector3 worldDir = ToWorldSpaceVector(dir);
m_auxGeomPtr->DrawCone(
worldPos,
worldDir,
radius,
height,
m_rendState.m_color,
AZ::RPI::AuxGeomDraw::DrawStyle::Line,
m_rendState.m_depthTest,
m_rendState.m_depthWrite,
m_rendState.m_faceCullMode,
m_rendState.m_viewProjOverrideIndex
);
}
}
void AtomDebugDisplayViewportInterface::DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded)
{
if (m_auxGeomPtr)
{
@@ -1336,8 +1380,6 @@ namespace AZ::AtomBridge
{
AZ_Assert(false, "Unexpected use of legacy api, please file a feature request with the rendering team to get this implemented!");
}
// unhandledled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
// void AtomDebugDisplayViewportInterface::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
void AtomDebugDisplayViewportInterface::SetLineWidth(float width)
{
@@ -153,6 +153,7 @@ namespace AZ::AtomBridge
void DrawTrianglesIndexed(const AZStd::vector<AZ::Vector3>& vertices, const AZStd::vector<AZ::u32>& indices, const AZ::Color& color) override;
void DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) override;
void DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) override;
void DrawWireOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) override;
void DrawSolidOBB(const AZ::Vector3& center, const AZ::Vector3& axisX, const AZ::Vector3& axisY, const AZ::Vector3& axisZ, const AZ::Vector3& halfExtents) override;
void DrawPoint(const AZ::Vector3& p, int nSize = 1) override;
void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) override;
@@ -167,7 +168,8 @@ namespace AZ::AtomBridge
void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) override;
void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) override;
void DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis = 2 /*z axis*/) override;
void DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) override;
void DrawWireCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height) override;
void DrawSolidCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) override;
void DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) override;
void DrawSolidCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height, bool drawShaded) override;
void DrawWireCapsule(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float heightStraightSection) override;
@@ -180,11 +182,8 @@ namespace AZ::AtomBridge
void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override;
void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override;
void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override;
// unhandled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
// void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override;
void SetLineWidth(float width) override;
bool IsVisible(const AZ::Aabb& bounds) override;
// int SetFillMode(int nFillMode) override;
float GetLineWidth() override;
float GetAspectRatio() override;
void DepthTestOff() override;
@@ -1786,18 +1786,17 @@ void AZ::FFont::DrawScreenAlignedText3d(
}
AZ::Vector3 positionNDC = AzFramework::WorldToScreenNDC(
params.m_position,
currentView->GetViewToWorldMatrix(),
currentView->GetWorldToViewMatrix(),
currentView->GetViewToClipMatrix()
);
AzFramework::TextDrawParameters param2d = params;
param2d.m_position = positionNDC;
internalParams.m_ctx.m_sizeIn800x600 = false;
DrawStringUInternal(
*internalParams.m_viewport,
internalParams.m_viewportContext,
internalParams.m_position.GetX(),
internalParams.m_position.GetY(),
params.m_position.GetZ(), // Z
positionNDC.GetX() * internalParams.m_viewport->GetWidth(),
(1.0f - positionNDC.GetY()) * internalParams.m_viewport->GetHeight(),
positionNDC.GetZ(), // Z
text.data(),
params.m_multiline,
internalParams.m_ctx
+6
View File
@@ -21,6 +21,9 @@ ly_add_target(
Include
BUILD_DEPENDENCIES
PUBLIC
AZ::AtomCore
Gem::Atom_RPI.Public
Gem::Atom_Bootstrap.Headers
Legacy::CryCommon
)
@@ -51,6 +54,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
Source
PUBLIC
Include
COMPILE_DEFINITIONS
PRIVATE
DEBUGDRAW_GEM_EDITOR=1
BUILD_DEPENDENCIES
PRIVATE
Gem::DebugDraw.Static
@@ -41,9 +41,8 @@ namespace DebugDraw
, m_worldLocation(AZ::Vector3::CreateZero())
, m_owningEditorComponent(AZ::InvalidComponentId)
, m_scale(AZ::Vector3(1.0f, 1.0f, 1.0f))
{
m_obb.CreateFromPositionRotationAndHalfLengths(m_worldLocation, AZ::Quaternion::CreateIdentity(), AZ::Vector3::CreateOne());
}
, m_obb(AZ::Obb::CreateFromPositionRotationAndHalfLengths(m_worldLocation, AZ::Quaternion::CreateIdentity(), AZ::Vector3::CreateOne()))
{}
};
class DebugDrawObbComponent
@@ -19,11 +19,6 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/parallel/lock.h>
#include <IRenderAuxGeom.h>
#include <Cry_Camera.h>
#include <MathConversion.h>
#include "DebugDrawSystemComponent.h"
// Editor specific
@@ -37,6 +32,9 @@
#include <AzToolsFramework/Entity/EditorEntityContextComponent.h>
#endif // DEBUGDRAW_GEM_EDITOR
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RPI.Public/Scene.h>
namespace DebugDraw
{
void DebugDrawSystemComponent::Reflect(AZ::ReflectContext* context)
@@ -96,7 +94,7 @@ namespace DebugDraw
void DebugDrawSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
(void)required;
required.push_back(AZ_CRC("RPISystem", 0xf2add773));
}
void DebugDrawSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
@@ -112,7 +110,7 @@ namespace DebugDraw
{
DebugDrawInternalRequestBus::Handler::BusConnect();
DebugDrawRequestBus::Handler::BusConnect();
AZ::TickBus::Handler::BusConnect();
AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect();
#ifdef DEBUGDRAW_GEM_EDITOR
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
@@ -125,7 +123,7 @@ namespace DebugDraw
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
#endif // DEBUGDRAW_GEM_EDITOR
AZ::TickBus::Handler::BusDisconnect();
AZ::RPI::SceneNotificationBus::Handler::BusDisconnect();
DebugDrawRequestBus::Handler::BusDisconnect();
DebugDrawInternalRequestBus::Handler::BusDisconnect();
@@ -155,6 +153,13 @@ namespace DebugDraw
}
}
void DebugDrawSystemComponent::OnBootstrapSceneReady(AZ::RPI::Scene* scene)
{
AZ_Assert(scene, "Invalid scene received in OnBootstrapSceneReady");
AZ::RPI::SceneNotificationBus::Handler::BusConnect(scene->GetId());
AZ::Render::Bootstrap::NotificationBus::Handler::BusDisconnect();
}
#ifdef DEBUGDRAW_GEM_EDITOR
void DebugDrawSystemComponent::OnStopPlayInEditor()
{
@@ -255,16 +260,26 @@ namespace DebugDraw
}
#endif // DEBUGDRAW_GEM_EDITOR
void DebugDrawSystemComponent::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint time)
void DebugDrawSystemComponent::OnBeginPrepareRender()
{
AZ::ScriptTimePoint time;
AZ::TickRequestBus::BroadcastResult(time, &AZ::TickRequestBus::Events::GetTimeAtCurrentTick);
m_currentTime = time.GetSeconds();
OnTickAabbs();
OnTickLines();
OnTickObbs();
OnTickRays();
OnTickSpheres();
OnTickText();
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(
debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId);
AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus.");
AzFramework::DebugDisplayRequests* debugDisplay =
AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
OnTickAabbs(*debugDisplay);
OnTickLines(*debugDisplay);
OnTickObbs(*debugDisplay);
OnTickRays(*debugDisplay);
OnTickSpheres(*debugDisplay);
OnTickText(*debugDisplay);
}
template <typename F>
@@ -277,7 +292,7 @@ namespace DebugDraw
vectorToExpire.erase(removalCondition, std::end(vectorToExpire));
}
void DebugDrawSystemComponent::OnTickAabbs()
void DebugDrawSystemComponent::OnTickAabbs(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeAabbsMutex);
@@ -295,17 +310,14 @@ namespace DebugDraw
AZ::Vector3 currentCenter = transformedAabb.GetCenter();
transformedAabb.Set(transformedAabb.GetMin() - currentCenter + aabbElement.m_worldLocation, transformedAabb.GetMax() - currentCenter + aabbElement.m_worldLocation);
}
ColorB lyColor(aabbElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(aabbElement.m_worldLocation));
AABB lyAABB(AZAabbToLyAABB(transformedAabb));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawAABB(lyAABB, false, lyColor, EBoundingBoxDrawStyle::eBBD_Extremes_Color_Encoded);
debugDisplay.SetColor(aabbElement.m_color);
debugDisplay.DrawSolidBox(transformedAabb.GetMin(), transformedAabb.GetMax());
}
removeExpiredDebugElementsFromVector(m_activeAabbs);
}
void DebugDrawSystemComponent::OnTickLines()
void DebugDrawSystemComponent::OnTickLines(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeLinesMutex);
size_t numActiveLines = m_activeLines.size();
@@ -339,26 +351,14 @@ namespace DebugDraw
&AZ::TransformBus::Events::GetWorldTranslation);
}
Vec3 start(AZVec3ToLYVec3(lineElement.m_startWorldLocation));
Vec3 end(AZVec3ToLYVec3(lineElement.m_endWorldLocation));
ColorB lyColor(lineElement.m_color.ToU32());
m_batchPoints.push_back(start);
m_batchPoints.push_back(end);
m_batchColors.push_back(lyColor);
m_batchColors.push_back(lyColor);
}
if (!m_batchPoints.empty())
{
gEnv->pRenderer->GetIRenderAuxGeom()->DrawLines(m_batchPoints.begin(), m_batchPoints.size(), m_batchColors.begin(), 1.0f);
debugDisplay.SetColor(lineElement.m_color);
debugDisplay.DrawLine(lineElement.m_startWorldLocation, lineElement.m_endWorldLocation);
}
removeExpiredDebugElementsFromVector(m_activeLines);
}
void DebugDrawSystemComponent::OnTickObbs()
void DebugDrawSystemComponent::OnTickObbs(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeObbsMutex);
@@ -382,20 +382,18 @@ namespace DebugDraw
transformedObb.SetHalfLength(i, obbElement.m_scale.GetElement(i));
}
}
obbElement.m_worldLocation = transformedObb.GetPosition();
ColorB lyColor(obbElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(obbElement.m_worldLocation));
OBB lyOBB(AZObbToLyOBB(transformedObb));
lyOBB.c = Vec3(0.f);
gEnv->pRenderer->GetIRenderAuxGeom()->DrawOBB(lyOBB, worldLocation, false, lyColor, EBoundingBoxDrawStyle::eBBD_Extremes_Color_Encoded);
else
{
obbElement.m_worldLocation = transformedObb.GetPosition();
}
debugDisplay.SetColor(obbElement.m_color);
debugDisplay.DrawSolidOBB(obbElement.m_worldLocation, transformedObb.GetAxisX(), transformedObb.GetAxisY(), transformedObb.GetAxisZ(), transformedObb.GetHalfLengths());
}
removeExpiredDebugElementsFromVector(m_activeObbs);
}
void DebugDrawSystemComponent::OnTickRays()
void DebugDrawSystemComponent::OnTickRays(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeRaysMutex);
@@ -415,22 +413,20 @@ namespace DebugDraw
rayElement.m_worldDirection = (endWorldLocation - rayElement.m_worldLocation);
}
ColorB lyColor(rayElement.m_color.ToU32());
Vec3 start(AZVec3ToLYVec3(rayElement.m_worldLocation));
Vec3 end(AZVec3ToLYVec3(endWorldLocation));
Vec3 direction(AZVec3ToLYVec3(rayElement.m_worldDirection));
float conePercentHeight = 0.5f;
float coneHeight = direction.GetLength() * conePercentHeight;
Vec3 coneBaseLocation = end - direction * conePercentHeight;
float coneHeight = rayElement.m_worldDirection.GetLength() * conePercentHeight;
AZ::Vector3 coneBaseLocation = endWorldLocation - rayElement.m_worldDirection * conePercentHeight;
float coneRadius = AZ::GetClamp(coneHeight * 0.07f, 0.05f, 0.2f);
gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(start, lyColor, coneBaseLocation, lyColor, 5.0f);
gEnv->pRenderer->GetIRenderAuxGeom()->DrawCone(coneBaseLocation, direction, coneRadius, coneHeight, lyColor, false);
debugDisplay.SetColor(rayElement.m_color);
debugDisplay.SetLineWidth(5.0f);
debugDisplay.DrawLine(rayElement.m_worldLocation, coneBaseLocation);
debugDisplay.DrawSolidCone(coneBaseLocation, rayElement.m_worldDirection, coneRadius, coneHeight, false);
}
removeExpiredDebugElementsFromVector(m_activeRays);
}
void DebugDrawSystemComponent::OnTickSpheres()
void DebugDrawSystemComponent::OnTickSpheres(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeSpheresMutex);
@@ -442,19 +438,14 @@ namespace DebugDraw
{
AZ::TransformBus::EventResult(sphereElement.m_worldLocation, sphereElement.m_targetEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
}
if (gEnv->pRenderer)
{
ColorB lyColor(sphereElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(sphereElement.m_worldLocation));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(worldLocation, sphereElement.m_radius, lyColor, true);
}
debugDisplay.SetColor(sphereElement.m_color);
debugDisplay.DrawBall(sphereElement.m_worldLocation, sphereElement.m_radius, true);
}
removeExpiredDebugElementsFromVector(m_activeSpheres);
}
void DebugDrawSystemComponent::OnTickText()
void DebugDrawSystemComponent::OnTickText(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZStd::lock_guard<AZStd::mutex> locker(m_activeTextsMutex);
@@ -471,30 +462,20 @@ namespace DebugDraw
#endif // DEBUGDRAW_GEM_EDITOR
// Draw text elements and remove any that are expired
AZStd::unordered_map<AZ::EntityId, AZ::u32> textPerEntityCount;
int numScreenTexts = 0;
AZ::EntityId lastTargetEntityId;
for (auto& textElement : m_activeTexts)
{
const AZ::Color textColor = needsGammaConversion ? textElement.m_color.GammaToLinear() : textElement.m_color;
debugDisplay.SetColor(textColor);
if (textElement.m_drawMode == DebugDrawTextElement::DrawMode::OnScreen)
{
const AZ::Color textColor = needsGammaConversion ? textElement.m_color.GammaToLinear() : textElement.m_color;
gEnv->pRenderer->GetIRenderAuxGeom()->Draw3dLabel(Vec3(20.f, 20.f + ((float)numScreenTexts * 15.0f), 0.5f), 1.4f, AZColorToLYColorF(textColor), textElement.m_text.c_str());
debugDisplay.Draw2dTextLabel(100.0f, 20.f + ((float)numScreenTexts * 15.0f), 1.4f, textElement.m_text.c_str() );
++numScreenTexts;
}
else if (textElement.m_drawMode == DebugDrawTextElement::DrawMode::InWorld)
{
SDrawTextInfo ti;
ti.xscale = ti.yscale = 1.4f;
ti.flags = eDrawText_2D | eDrawText_FixedSize | eDrawText_Monospace | eDrawText_Center;
const AZ::Color textColor = needsGammaConversion ? textElement.m_color.GammaToLinear() : textElement.m_color;
ti.color[0] = textColor.GetR();
ti.color[1] = textColor.GetG();
ti.color[2] = textColor.GetB();
ti.color[3] = textColor.GetA();
AZ::Vector3 worldLocation;
if (textElement.m_targetEntityId.IsValid())
{
@@ -507,32 +488,7 @@ namespace DebugDraw
worldLocation = textElement.m_worldLocation;
}
const CCamera& camera = gEnv->pSystem->GetViewCamera();
const AZ::Vector3 cameraTranslation = LYVec3ToAZVec3(camera.GetPosition());
Vec3 lyWorldLoc = AZVec3ToLYVec3(worldLocation);
Vec3 screenPos(0.f);
if (camera.Project(lyWorldLoc, screenPos, Vec2i(0, 0), Vec2i(0, 0)))
{
// Handle spacing for world text so it doesn't draw on top of each other
// This works for text drawing on entities (considered one block), but not for world text.
// World text will get handled when we have screen-aware positioning of text elements
if (textElement.m_targetEntityId.IsValid())
{
auto iter = textPerEntityCount.find(textElement.m_targetEntityId);
if (iter != textPerEntityCount.end())
{
AZ::u32 count = iter->second;
screenPos.y += ((float)count * 15.0f);
iter->second = count + 1;
}
else
{
auto newEntry = textPerEntityCount.insert_key(textElement.m_targetEntityId);
newEntry.first->second = 1;
}
}
gEnv->pRenderer->GetIRenderAuxGeom()->Draw3dLabel(Vec3(screenPos.x, screenPos.y, 0.5f), 1.4f, AZColorToLYColorF(textColor), textElement.m_text.c_str());
}
debugDisplay.DrawTextLabel(worldLocation, 1.4f, textElement.m_text.c_str() );
}
}
@@ -550,9 +506,9 @@ namespace DebugDraw
CreateLineEntryForComponent(lineComponent->GetEntityId(), lineComponent->m_element);
}
#ifdef DEBUGDRAW_GEM_EDITOR
else if (EditorDebugDrawLineComponent* lineComponent = azrtti_cast<EditorDebugDrawLineComponent*>(component))
else if (EditorDebugDrawLineComponent* editorLineComponent = azrtti_cast<EditorDebugDrawLineComponent*>(component))
{
CreateLineEntryForComponent(lineComponent->GetEntityId(), lineComponent->m_element);
CreateLineEntryForComponent(editorLineComponent->GetEntityId(), editorLineComponent->m_element);
}
#endif // DEBUGDRAW_GEM_EDITOR
else if (DebugDrawRayComponent* rayComponent = azrtti_cast<DebugDrawRayComponent*>(component))
@@ -560,9 +516,9 @@ namespace DebugDraw
CreateRayEntryForComponent(rayComponent->GetEntityId(), rayComponent->m_element);
}
#ifdef DEBUGDRAW_GEM_EDITOR
else if (EditorDebugDrawRayComponent* rayComponent = azrtti_cast<EditorDebugDrawRayComponent*>(component))
else if (EditorDebugDrawRayComponent* editorRayComponent = azrtti_cast<EditorDebugDrawRayComponent*>(component))
{
CreateRayEntryForComponent(rayComponent->GetEntityId(), rayComponent->m_element);
CreateRayEntryForComponent(editorRayComponent->GetEntityId(), editorRayComponent->m_element);
}
#endif // DEBUGDRAW_GEM_EDITOR
else if (DebugDrawSphereComponent* sphereComponent = azrtti_cast<DebugDrawSphereComponent*>(component))
@@ -570,9 +526,9 @@ namespace DebugDraw
CreateSphereEntryForComponent(sphereComponent->GetEntityId(), sphereComponent->m_element);
}
#ifdef DEBUGDRAW_GEM_EDITOR
else if (EditorDebugDrawSphereComponent* sphereComponent = azrtti_cast<EditorDebugDrawSphereComponent*>(component))
else if (EditorDebugDrawSphereComponent* editorSphereComponent = azrtti_cast<EditorDebugDrawSphereComponent*>(component))
{
CreateSphereEntryForComponent(sphereComponent->GetEntityId(), sphereComponent->m_element);
CreateSphereEntryForComponent(editorSphereComponent->GetEntityId(), editorSphereComponent->m_element);
}
#endif // DEBUGDRAW_GEM_EDITOR
else if (DebugDrawObbComponent* obbComponent = azrtti_cast<DebugDrawObbComponent*>(component))
@@ -581,9 +537,9 @@ namespace DebugDraw
}
#ifdef DEBUGDRAW_GEM_EDITOR
else if (EditorDebugDrawObbComponent* obbComponent = azrtti_cast<EditorDebugDrawObbComponent*>(component))
else if (EditorDebugDrawObbComponent* editorObbComponent = azrtti_cast<EditorDebugDrawObbComponent*>(component))
{
CreateObbEntryForComponent(obbComponent->GetEntityId(), obbComponent->m_element);
CreateObbEntryForComponent(editorObbComponent->GetEntityId(), editorObbComponent->m_element);
}
#endif // DEBUGDRAW_GEM_EDITOR
@@ -593,9 +549,9 @@ namespace DebugDraw
}
#ifdef DEBUGDRAW_GEM_EDITOR
else if (EditorDebugDrawTextComponent* textComponent = azrtti_cast<EditorDebugDrawTextComponent*>(component))
else if (EditorDebugDrawTextComponent* editorTextComponent = azrtti_cast<EditorDebugDrawTextComponent*>(component))
{
CreateTextEntryForComponent(textComponent->GetEntityId(), textComponent->m_element);
CreateTextEntryForComponent(editorTextComponent->GetEntityId(), editorTextComponent->m_element);
}
#endif // DEBUGDRAW_GEM_EDITOR
}
@@ -32,6 +32,9 @@
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#endif // DEBUGDRAW_GEM_EDITOR
#include <Atom/RPI.Public/SceneBus.h>
#include <Atom/Bootstrap/BootstrapNotificationBus.h>
namespace DebugDraw
{
// DebugDraw elements that don't have corresponding component representations yet
@@ -61,10 +64,11 @@ namespace DebugDraw
class DebugDrawSystemComponent
: public AZ::Component
, public AZ::TickBus::Handler
, public AZ::EntityBus::MultiHandler
, protected DebugDrawRequestBus::Handler
, protected DebugDrawInternalRequestBus::Handler
, public AZ::RPI::SceneNotificationBus::Handler
, public AZ::Render::Bootstrap::NotificationBus::Handler
#ifdef DEBUGDRAW_GEM_EDITOR
, protected AzToolsFramework::EditorEntityContextNotificationBus::Handler
@@ -113,20 +117,22 @@ namespace DebugDraw
void Activate() override;
void Deactivate() override;
// TickBus
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
int GetTickOrder() override { return AZ::ComponentTickBus::TICK_DEFAULT; }
// SceneNotificationBus
void OnBeginPrepareRender() override;
// AZ::Render::Bootstrap::NotificationBus
void OnBootstrapSceneReady(AZ::RPI::Scene* scene);
// EntityBus
void OnEntityDeactivated(const AZ::EntityId& entityId) override;
// Ticking functions for drawing debug elements
void OnTickAabbs();
void OnTickLines();
void OnTickObbs();
void OnTickRays();
void OnTickSpheres();
void OnTickText();
void OnTickAabbs(AzFramework::DebugDisplayRequests& debugDisplay);
void OnTickLines(AzFramework::DebugDisplayRequests& debugDisplay);
void OnTickObbs(AzFramework::DebugDisplayRequests& debugDisplay);
void OnTickRays(AzFramework::DebugDisplayRequests& debugDisplay);
void OnTickSpheres(AzFramework::DebugDisplayRequests& debugDisplay);
void OnTickText(AzFramework::DebugDisplayRequests& debugDisplay);
// Element creation functions, used when DebugDraw components register themselves
void CreateAabbEntryForComponent(const AZ::EntityId& componentEntityId, const DebugDrawAabbElement& element);
@@ -154,7 +160,7 @@ namespace DebugDraw
double m_currentTime;
AZStd::vector<Vec3> m_batchPoints;
AZStd::vector<ColorB> m_batchColors;
AZStd::vector<AZ::Vector3> m_batchPoints;
AZStd::vector<AZ::Color> m_batchColors;
};
}
@@ -11,6 +11,3 @@
*/
#pragma once
#include <platform.h> // Many CryCommon files require that this is included first.
#include <Cry_Color.h>
@@ -72,11 +72,6 @@ namespace SceneBuilder
m_sceneBuilder.BusDisconnect();
}
void BuilderPluginComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.emplace_back(AZ_CRC_CE("AssetImportRequestHandler"));
}
void BuilderPluginComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
@@ -86,4 +81,5 @@ namespace SceneBuilder
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AssetBuilderSDK::ComponentTags::AssetBuilder }));
}
}
} // namespace SceneBuilder
@@ -32,8 +32,6 @@ namespace SceneBuilder
void Activate() override;
void Deactivate() override;
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
private:
SceneBuilderWorker m_sceneBuilder;
};
-16
View File
@@ -1,16 +0,0 @@
{
"O3DE":
{
"SceneAPI":
{
"AssetImporter":
{
"SupportedFileTypeExtensions":
[
".fbx",
".stl"
]
}
}
}
}
+3 -3
View File
@@ -29,15 +29,15 @@ string(TOLOWER ${PROJECT_NAME} _project_name_lower)
set(CPACK_PACKAGE_FILE_NAME "${_project_name_lower}_${LY_VERSION_STRING}_installer")
set(DEFAULT_LICENSE_NAME "Apache-2.0")
set(DEFAULT_LICENSE_FILE "${CMAKE_SOURCE_DIR}/LICENSE.txt")
set(DEFAULT_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE})
set(CPACK_LICENSE_URL ${LY_INSTALLER_LICENSE_URL})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_VERSION}")
# CMAKE_SOURCE_DIR doesn't equate to anything during execution of pre/post build scripts
set(CPACK_SOURCE_DIR ${CMAKE_SOURCE_DIR}/cmake)
# neither of the SOURCE_DIR variables equate to anything during execution of pre/post build scripts
set(CPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# attempt to apply platform specific settings
ly_get_absolute_pal_filename(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME})