Merge remote-tracking branch 'upstream/development' into Atom/santorac/MaterialPropertyRenameInMaterialComponent

monroegm-disable-blank-issue-2
santorac 4 years ago
commit cef1e200f6

@ -17,3 +17,392 @@ LIGHT_TYPES = {
'simple_point': 6, 'simple_point': 6,
'simple_spot': 7, 'simple_spot': 7,
} }
class AtomComponentProperties:
"""
Holds Atom component related constants
"""
@staticmethod
def actor(property: str = 'name') -> str:
"""
Actor component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Actor',
}
return properties[property]
@staticmethod
def bloom(property: str = 'name') -> str:
"""
Bloom component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Bloom',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def camera(property: str = 'name') -> str:
"""
Camera component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Camera',
}
return properties[property]
@staticmethod
def decal(property: str = 'name') -> str:
"""
Decal component properties.
- 'Material' the material Asset.id of the decal.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Decal',
'Material': 'Controller|Configuration|Material',
}
return properties[property]
@staticmethod
def deferred_fog(property: str = 'name') -> str:
"""
Deferred Fog component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Deferred Fog',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def depth_of_field(property: str = 'name') -> str:
"""
Depth of Field component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
- 'Camera Entity' an EditorEntity.id reference to the Camera component required for this effect.
Must be a different entity than the one which hosts Depth of Field component.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'DepthOfField',
'requires': [AtomComponentProperties.postfx_layer()],
'Camera Entity': 'Controller|Configuration|Camera Entity',
}
return properties[property]
@staticmethod
def diffuse_probe(property: str = 'name') -> str:
"""
Diffuse Probe Grid component properties. Requires one of 'shapes'.
- 'shapes' a list of supported shapes as component names.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Diffuse Probe Grid',
'shapes': ['Axis Aligned Box Shape', 'Box Shape']
}
return properties[property]
@staticmethod
def directional_light(property: str = 'name') -> str:
"""
Directional Light component properties.
- 'Camera' an EditorEntity.id reference to the Camera component that controls cascaded shadow view frustum.
Must be a different entity than the one which hosts Directional Light component.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Directional Light',
'Camera': 'Controller|Configuration|Shadow|Camera',
}
return properties[property]
@staticmethod
def display_mapper(property: str = 'name') -> str:
"""
Display Mapper component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Display Mapper',
}
return properties[property]
@staticmethod
def entity_reference(property: str = 'name') -> str:
"""
Entity Reference component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Entity Reference',
}
return properties[property]
@staticmethod
def exposure_control(property: str = 'name') -> str:
"""
Exposure Control component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Exposure Control',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def global_skylight(property: str = 'name') -> str:
"""
Global Skylight (IBL) component properties.
- 'Diffuse Image' Asset.id for the cubemap image for determining diffuse lighting.
- 'Specular Image' Asset.id for the cubemap image for determining specular lighting.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Global Skylight (IBL)',
'Diffuse Image': 'Controller|Configuration|Diffuse Image',
'Specular Image': 'Controller|Configuration|Specular Image',
}
return properties[property]
@staticmethod
def grid(property: str = 'name') -> str:
"""
Grid component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Grid',
}
return properties[property]
@staticmethod
def hdr_color_grading(property: str = 'name') -> str:
"""
HDR Color Grading component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'HDR Color Grading',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def hdri_skybox(property: str = 'name') -> str:
"""
HDRi Skybox component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'HDRi Skybox',
}
return properties[property]
@staticmethod
def light(property: str = 'name') -> str:
"""
Light component properties.
- 'Light type' from atom_constants.py LIGHT_TYPES
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Light',
'Light type': 'Controller|Configuration|Light type',
}
return properties[property]
@staticmethod
def look_modification(property: str = 'name') -> str:
"""
Look Modification component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Look Modification',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def material(property: str = 'name') -> str:
"""
Material component properties. Requires one of Actor OR Mesh component.
- 'requires' a list of component names as strings required by this component.
Only one of these is required at a time for this component.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Material',
'requires': [AtomComponentProperties.actor(), AtomComponentProperties.mesh()],
}
return properties[property]
@staticmethod
def mesh(property: str = 'name') -> str:
"""
Mesh component properties.
- 'Mesh Asset' Asset.id of the mesh model.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
:rtype: str
"""
properties = {
'name': 'Mesh',
'Mesh Asset': 'Controller|Configuration|Mesh Asset',
}
return properties[property]
@staticmethod
def occlusion_culling_plane(property: str = 'name') -> str:
"""
Occlusion Culling Plane component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Occlusion Culling Plane',
}
return properties[property]
@staticmethod
def physical_sky(property: str = 'name') -> str:
"""
Physical Sky component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Physical Sky',
}
return properties[property]
@staticmethod
def postfx_layer(property: str = 'name') -> str:
"""
PostFX Layer component properties.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'PostFX Layer',
}
return properties[property]
@staticmethod
def postfx_gradient(property: str = 'name') -> str:
"""
PostFX Gradient Weight Modifier component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'PostFX Gradient Weight Modifier',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def postfx_radius(property: str = 'name') -> str:
"""
PostFX Radius Weight Modifier component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'PostFX Radius Weight Modifier',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]
@staticmethod
def postfx_shape(property: str = 'name') -> str:
"""
PostFX Shape Weight Modifier component properties. Requires PostFX Layer and one of 'shapes' listed.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
- 'shapes' a list of supported shapes as component names. 'Tube Shape' is also supported but requires 'Spline'.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'PostFX Shape Weight Modifier',
'requires': [AtomComponentProperties.postfx_layer()],
'shapes': ['Axis Aligned Box Shape', 'Box Shape', 'Capsule Shape', 'Compound Shape', 'Cylinder Shape',
'Disk Shape', 'Polygon Prism Shape', 'Quad Shape', 'Sphere Shape', 'Vegetation Reference Shape'],
}
return properties[property]
@staticmethod
def reflection_probe(property: str = 'name') -> str:
"""
Reflection Probe component properties. Requires one of 'shapes' listed.
- 'shapes' a list of supported shapes as component names.
- 'Baked Cubemap Path' Asset.id of the baked cubemap image generated by a call to 'BakeReflectionProbe' ebus.
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'Reflection Probe',
'shapes': ['Axis Aligned Box Shape', 'Box Shape'],
'Baked Cubemap Path': 'Cubemap|Baked Cubemap Path',
}
return properties[property]
@staticmethod
def ssao(property: str = 'name') -> str:
"""
SSAO component properties. Requires PostFX Layer component.
- 'requires' a list of component names as strings required by this component.
Use editor_entity_utils EditorEntity.add_components(list) to add this list of requirements.\n
:param property: From the last element of the property tree path. Default 'name' for component name string.
:return: Full property path OR component name if no property specified.
"""
properties = {
'name': 'SSAO',
'requires': [AtomComponentProperties.postfx_layer()],
}
return properties[property]

@ -80,25 +80,25 @@ def AtomEditorComponents_Mesh_AddedToEntity():
from editor_python_test_tools.asset_utils import Asset from editor_python_test_tools.asset_utils import Asset
from editor_python_test_tools.editor_entity_utils import EditorEntity from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper from editor_python_test_tools.utils import Report, Tracer, TestHelper
from Atom.atom_utils.atom_constants import AtomComponentProperties as Atom
with Tracer() as error_tracer: with Tracer() as error_tracer:
# Test setup begins. # Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
helper.init_idle() TestHelper.init_idle()
helper.open_level("", "Base") TestHelper.open_level("", "Base")
# Test steps begin. # Test steps begin.
# 1. Create a Mesh entity with no components. # 1. Create a Mesh entity with no components.
mesh_name = "Mesh" mesh_entity = EditorEntity.create_editor_entity(Atom.mesh())
mesh_entity = EditorEntity.create_editor_entity(mesh_name)
Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists()) Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists())
# 2. Add a Mesh component to Mesh entity. # 2. Add a Mesh component to Mesh entity.
mesh_component = mesh_entity.add_component(mesh_name) mesh_component = mesh_entity.add_component(Atom.mesh())
Report.critical_result( Report.critical_result(
Tests.mesh_component_added, Tests.mesh_component_added,
mesh_entity.has_component(mesh_name)) mesh_entity.has_component(Atom.mesh()))
# 3. UNDO the entity creation and component addition. # 3. UNDO the entity creation and component addition.
# -> UNDO component addition. # -> UNDO component addition.
@ -125,17 +125,16 @@ def AtomEditorComponents_Mesh_AddedToEntity():
Report.result(Tests.creation_redo, mesh_entity.exists()) Report.result(Tests.creation_redo, mesh_entity.exists())
# 5. Set Mesh component asset property # 5. Set Mesh component asset property
mesh_property_asset = 'Controller|Configuration|Mesh Asset'
model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel') model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel')
model = Asset.find_asset_by_path(model_path) model = Asset.find_asset_by_path(model_path)
mesh_component.set_component_property_value(mesh_property_asset, model.id) mesh_component.set_component_property_value(Atom.mesh('Mesh Asset'), model.id)
Report.result(Tests.mesh_asset_specified, Report.result(Tests.mesh_asset_specified,
mesh_component.get_component_property_value(mesh_property_asset) == model.id) mesh_component.get_component_property_value(Atom.mesh('Mesh Asset')) == model.id)
# 6. Enter/Exit game mode. # 6. Enter/Exit game mode.
helper.enter_game_mode(Tests.enter_game_mode) TestHelper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1) general.idle_wait_frames(1)
helper.exit_game_mode(Tests.exit_game_mode) TestHelper.exit_game_mode(Tests.exit_game_mode)
# 7. Test IsHidden. # 7. Test IsHidden.
mesh_entity.set_visibility_state(False) mesh_entity.set_visibility_state(False)
@ -159,7 +158,7 @@ def AtomEditorComponents_Mesh_AddedToEntity():
Report.result(Tests.deletion_redo, not mesh_entity.exists()) Report.result(Tests.deletion_redo, not mesh_entity.exists())
# 12. Look for errors or asserts. # 12. Look for errors or asserts.
helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
for error_info in error_tracer.errors: for error_info in error_tracer.errors:
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
for assert_info in error_tracer.asserts: for assert_info in error_tracer.asserts:

@ -6,10 +6,7 @@
* *
*/ */
#include "EditorDefs.h" #include "EditorDefs.h"
#include "AboutDialog.h" #include "AboutDialog.h"
// Qt // Qt
@ -47,14 +44,17 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }"); CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }");
// Prepare background image // Prepare background image
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( QPixmap image = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
screen(), screen(), QSize(m_imageWidth, m_imageHeight),
QSize(m_enforcedWidth, m_enforcedHeight),
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation Qt::SmoothTransformation
); );
// Crop image to cut out transparent border
QRect cropRect((m_imageWidth - m_enforcedWidth) / 2, (m_imageHeight - m_enforcedHeight) / 2, m_enforcedWidth, m_enforcedHeight);
m_backgroundImage = AzQtComponents::CropPixmapForScreenDpi(image, screen(), cropRect);
// Draw the Open 3D Engine logo from svg // Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));

@ -38,7 +38,9 @@ private:
QScopedPointer<Ui::CAboutDialog> m_ui; QScopedPointer<Ui::CAboutDialog> m_ui;
QPixmap m_backgroundImage; QPixmap m_backgroundImage;
int m_enforcedWidth = 600; const int m_imageWidth = 668;
int m_enforcedHeight = 400; const int m_imageHeight = 368;
const int m_enforcedWidth = 600;
const int m_enforcedHeight = 300;
}; };

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>600</width>
<height>360</height> <height>300</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -19,13 +19,13 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>600</width> <width>600</width>
<height>360</height> <height>300</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>600</width> <width>608</width>
<height>360</height> <height>300</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -69,7 +69,7 @@
<number>11</number> <number>11</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>12</number> <number>10</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>12</number> <number>12</number>
@ -125,7 +125,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Developer Preview</string> <string>General Availability</string>
</property> </property>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::AutoText</enum> <enum>Qt::AutoText</enum>

@ -34,11 +34,12 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_ui->setupUi(this); m_ui->setupUi(this);
s_pLogoWindow = this; s_pLogoWindow = this;
setFixedSize(QSize(600, 300)); setFixedSize(QSize(m_enforcedWidth, m_enforcedHeight));
setAttribute(Qt::WA_TranslucentBackground, true);
// Prepare background image // Prepare background image
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_2021_11.jpg")),
screen(), screen(),
QSize(m_enforcedWidth, m_enforcedHeight), QSize(m_enforcedWidth, m_enforcedHeight),
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,

@ -50,7 +50,7 @@ private:
QScopedPointer<Ui::StartupLogoDialog> m_ui; QScopedPointer<Ui::StartupLogoDialog> m_ui;
QPixmap m_backgroundImage; QPixmap m_backgroundImage;
const int m_enforcedWidth = 600; const int m_enforcedWidth = 668;
const int m_enforcedHeight = 300; const int m_enforcedHeight = 368;
}; };

@ -1,6 +1,6 @@
<RCC> <RCC>
<qresource prefix="/StartupLogoDialog"> <qresource prefix="/StartupLogoDialog">
<file>o3de_logo.svg</file> <file>o3de_logo.svg</file>
<file>splashscreen_background_developer_preview.jpg</file> <file>splashscreen_background_2021_11.jpg</file>
</qresource> </qresource>
</RCC> </RCC>

@ -6,13 +6,22 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>668</width>
<height>300</height> <height>368</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>50</number>
</property>
<property name="topMargin">
<number>42</number>
</property>
<property name="rightMargin">
<number>42</number>
</property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>9</number> <number>42</number>
</property> </property>
<property name="verticalSpacing"> <property name="verticalSpacing">
<number>10</number> <number>10</number>
@ -29,7 +38,7 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>250</width> <width>300</width>
<height>20</height> <height>20</height>
</size> </size>
</property> </property>
@ -53,7 +62,7 @@
<number>1</number> <number>1</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>28</number> <number>20</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>24</number> <number>24</number>
@ -94,7 +103,7 @@
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Developer Preview</string> <string>General Availability</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -153,20 +162,28 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>290</width> <width>290</width>
<height>0</height> <height>32</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>290</width> <width>290</width>
<height>16777215</height> <height>32</height>
</size> </size>
</property> </property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Starting Editor...</string> <string>Starting Editor...</string>
</property> </property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
</widget> </widget>
</item> </item>

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ffcb7614bed0790bf58a2bb7b2d70958289cb2edf562acc8fc841f4c50a55445
size 2974586

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7105ec99477f124a8ac8d588f2dfc4ee7bb54f39386c8131b7703c86754c0cb8
size 248690

@ -58,6 +58,7 @@
#include <AzFramework/Script/ScriptComponent.h> #include <AzFramework/Script/ScriptComponent.h>
#include <AzFramework/Spawnable/SpawnableSystemComponent.h> #include <AzFramework/Spawnable/SpawnableSystemComponent.h>
#include <AzFramework/StreamingInstall/StreamingInstall.h> #include <AzFramework/StreamingInstall/StreamingInstall.h>
#include <AzFramework/SurfaceData/SurfaceData.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h> #include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzFramework/Viewport/CameraState.h> #include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h> #include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h>
@ -278,6 +279,8 @@ namespace AzFramework
AzFramework::RemoteStorageDriveConfig::Reflect(context); AzFramework::RemoteStorageDriveConfig::Reflect(context);
Physics::ReflectionUtils::ReflectPhysicsApi(context); Physics::ReflectionUtils::ReflectPhysicsApi(context);
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
AzFramework::SurfaceData::SurfacePoint::Reflect(context);
AzFramework::Terrain::TerrainDataRequests::Reflect(context); AzFramework::Terrain::TerrainDataRequests::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))

@ -286,12 +286,17 @@ namespace Physics
return m_type; return m_type;
} }
void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const const void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
{ {
return m_cachedNativeMesh; return m_cachedNativeMesh;
} }
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) const void* CookedMeshShapeConfiguration::GetCachedNativeMesh()
{
return m_cachedNativeMesh;
}
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh)
{ {
m_cachedNativeMesh = cachedNativeMesh; m_cachedNativeMesh = cachedNativeMesh;
} }
@ -353,12 +358,17 @@ namespace Physics
return *this; return *this;
} }
void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const const void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield() const
{ {
return m_cachedNativeHeightfield; return m_cachedNativeHeightfield;
} }
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield) const void* HeightfieldShapeConfiguration::GetCachedNativeHeightfield()
{
return m_cachedNativeHeightfield;
}
void HeightfieldShapeConfiguration::SetCachedNativeHeightfield(void* cachedNativeHeightfield)
{ {
if (m_cachedNativeHeightfield) if (m_cachedNativeHeightfield)
{ {
@ -427,4 +437,5 @@ namespace Physics
{ {
m_maxHeightBounds = maxBounds; m_maxHeightBounds = maxBounds;
} }
} } // namespace Physics

@ -187,8 +187,9 @@ namespace Physics
MeshType GetMeshType() const; MeshType GetMeshType() const;
void* GetCachedNativeMesh() const; void* GetCachedNativeMesh();
void SetCachedNativeMesh(void* cachedNativeMesh) const; const void* GetCachedNativeMesh() const;
void SetCachedNativeMesh(void* cachedNativeMesh);
private: private:
void ReleaseCachedNativeMesh(); void ReleaseCachedNativeMesh();
@ -197,7 +198,7 @@ namespace Physics
MeshType m_type = MeshType::TriangleMesh; MeshType m_type = MeshType::TriangleMesh;
//! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized. //! Cached native mesh object (e.g. PxConvexMesh or PxTriangleMesh). This data is not serialized.
mutable void* m_cachedNativeMesh = nullptr; void* m_cachedNativeMesh = nullptr;
}; };
class HeightfieldShapeConfiguration class HeightfieldShapeConfiguration
@ -217,8 +218,9 @@ namespace Physics
return ShapeType::Heightfield; return ShapeType::Heightfield;
} }
void* GetCachedNativeHeightfield() const; const void* GetCachedNativeHeightfield() const;
void SetCachedNativeHeightfield(void* cachedNativeHeightfield) const; void* GetCachedNativeHeightfield();
void SetCachedNativeHeightfield(void* cachedNativeHeightfield);
AZ::Vector2 GetGridResolution() const; AZ::Vector2 GetGridResolution() const;
void SetGridResolution(const AZ::Vector2& gridSpacing); void SetGridResolution(const AZ::Vector2& gridSpacing);
int32_t GetNumColumns() const; int32_t GetNumColumns() const;
@ -246,6 +248,6 @@ namespace Physics
//! The grid of sample points for the heightfield. //! The grid of sample points for the heightfield.
AZStd::vector<Physics::HeightMaterialPoint> m_samples; AZStd::vector<Physics::HeightMaterialPoint> m_samples;
//! An optional storage pointer for the physics system to cache its native heightfield representation. //! An optional storage pointer for the physics system to cache its native heightfield representation.
mutable void* m_cachedNativeHeightfield{ nullptr }; void* m_cachedNativeHeightfield{ nullptr };
}; };
} // namespace Physics } // namespace Physics

@ -0,0 +1,59 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/SurfaceData/SurfaceData.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AzFramework::SurfaceData
{
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SurfaceTagWeight>()
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType)
->Field("m_weight", &SurfaceTagWeight::m_weight)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<SurfaceTagWeight>()
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
->Constructor()
->Property("surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType))
->Property("weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight))
;
}
}
void SurfacePoint::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<SurfacePoint>()
->Field("m_position", &SurfacePoint::m_position)
->Field("m_normal", &SurfacePoint::m_normal)
->Field("m_surfaceTags", &SurfacePoint::m_surfaceTags)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<SurfacePoint>("AzFramework::SurfaceData::SurfacePoint")
->Attribute(AZ::Script::Attributes::Category, "SurfaceData")
->Constructor()
->Property("position", BehaviorValueProperty(&SurfacePoint::m_position))
->Property("normal", BehaviorValueProperty(&SurfacePoint::m_normal))
->Property("surfaceTags", BehaviorValueProperty(&SurfacePoint::m_surfaceTags))
;
}
}
} // namespace AzFramework::SurfaceData

@ -0,0 +1,72 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Math/Crc.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/std/containers/vector.h>
namespace AzFramework::SurfaceData
{
namespace Constants
{
static constexpr const char* s_unassignedTagName = "(unassigned)";
}
struct SurfaceTagWeight
{
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
SurfaceTagWeight() = default;
SurfaceTagWeight(AZ::Crc32 surfaceType, float weight)
: m_surfaceType(surfaceType)
, m_weight(weight)
{
}
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
static void Reflect(AZ::ReflectContext* context);
};
struct SurfaceTagWeightComparator
{
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
{
// Return a deterministic sort order for surface tags from highest to lowest weight, with the surface types sorted
// in a predictable order when the weights are equal. The surface type sort order is meaningless since it is sorting CRC
// values, it's really just important for it to be stable.
// For the floating-point weight comparisons we use exact instead of IsClose value comparisons for a similar reason - we
// care about being sorted highest to lowest, but there's no inherent meaning in sorting surface types with *similar* weights
// together.
if (tagWeight1.m_weight != tagWeight2.m_weight)
{
return tagWeight1.m_weight > tagWeight2.m_weight;
}
else
{
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
}
}
};
using SurfaceTagWeightList = AZStd::vector<SurfaceTagWeight>;
struct SurfacePoint final
{
AZ_TYPE_INFO(SurfacePoint, "{331A3D0E-BB1D-47BF-96A2-249FAA0D720D}");
AZ::Vector3 m_position;
AZ::Vector3 m_normal;
SurfaceTagWeightList m_surfaceTags;
static void Reflect(AZ::ReflectContext* context);
};
} // namespace AzFramework::SurfaceData

@ -8,56 +8,33 @@
#include "TerrainDataRequestBus.h" #include "TerrainDataRequestBus.h"
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AzFramework namespace AzFramework::Terrain
{ {
namespace SurfaceData void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
{ {
void SurfaceTagWeight::Reflect(AZ::ReflectContext* context) if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{ {
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
{ ->Attribute(AZ::Script::Attributes::Category, "Terrain")
serializeContext->Class<SurfaceTagWeight>() ->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
->Field("m_surfaceType", &SurfaceTagWeight::m_surfaceType) ->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Field("m_weight", &SurfaceTagWeight::m_weight) ->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
; ->Event("GetMaxSurfaceWeightFromVector2",
} &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromVector2)
->Event("GetSurfaceWeights", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeights)
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) ->Event("GetSurfaceWeightsFromVector2",
{ &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfaceWeightsFromVector2)
behaviorContext->Class<SurfaceTagWeight>("SurfaceTagWeight") ->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
->Property("m_surfaceType", BehaviorValueProperty(&SurfaceTagWeight::m_surfaceType)) ->Event("GetSurfacePoint", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePoint)
->Property("m_weight", BehaviorValueProperty(&SurfaceTagWeight::m_weight)) ->Event("GetSurfacePointFromVector2",
; &AzFramework::Terrain::TerrainDataRequestBus::Events::GetSurfacePointFromVector2)
} ->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
} ->Event("GetTerrainHeightQueryResolution",
} //namespace SurfaceData &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
;
namespace Terrain
{
void TerrainDataRequests::Reflect(AZ::ReflectContext* context)
{
AzFramework::SurfaceData::SurfaceTagWeight::Reflect(context);
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<AzFramework::Terrain::TerrainDataRequestBus>("TerrainDataRequestBus")
->Attribute(AZ::Script::Attributes::Category, "Terrain")
->Event("GetHeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeight)
->Event("GetHeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetHeightFromFloats)
->Event("GetMaxSurfaceWeight", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeight)
->Event("GetMaxSurfaceWeightFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetMaxSurfaceWeightFromFloats)
->Event("GetIsHoleFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetIsHoleFromFloats)
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats)
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
->Event("GetTerrainHeightQueryResolution",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
;
}
} }
} //namespace Terrain }
} // namespace AzFramework } // namespace AzFramework::Terrain

@ -8,50 +8,13 @@
#pragma once #pragma once
#include <AzCore/EBus/EBus.h> #include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/Math/Vector2.h> #include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Aabb.h> #include <AzCore/Math/Aabb.h>
#include <AzCore/RTTI/BehaviorContext.h> #include <AzFramework/SurfaceData/SurfaceData.h>
namespace AzFramework namespace AzFramework
{ {
namespace SurfaceData
{
namespace Constants
{
static const char* s_unassignedTagName = "(unassigned)";
}
struct SurfaceTagWeight
{
AZ_TYPE_INFO(SurfaceTagWeight, "{EA14018E-E853-4BF5-8E13-D83BB99A54CC}");
AZ::Crc32 m_surfaceType = AZ::Crc32(Constants::s_unassignedTagName);
float m_weight = 0.0f; //! A Value in the range [0.0f .. 1.0f]
//! Don't call this directly. TerrainDataRequests::Reflect is doing it already.
static void Reflect(AZ::ReflectContext* context);
};
struct SurfaceTagWeightComparator
{
bool operator()(const SurfaceTagWeight& tagWeight1, const SurfaceTagWeight& tagWeight2) const
{
if (!AZ::IsClose(tagWeight1.m_weight, tagWeight2.m_weight))
{
return tagWeight1.m_weight > tagWeight2.m_weight;
}
else
{
return tagWeight1.m_surfaceType > tagWeight2.m_surfaceType;
}
}
};
using OrderedSurfaceTagWeightSet = AZStd::set<SurfaceTagWeight, SurfaceTagWeightComparator>;
} //namespace SurfaceData
namespace Terrain namespace Terrain
{ {
@ -91,49 +54,82 @@ namespace AzFramework
//! Returns terrains height in meters at location x,y. //! Returns terrains height in meters at location x,y.
//! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false, //! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false,
//! otherwise *terrainExistsPtr will become true. //! otherwise *terrainExistsPtr will become true.
virtual float GetHeight(AZ::Vector3 position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; virtual float GetHeight(const AZ::Vector3& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeightFromFloats(float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; virtual float GetHeightFromVector2(
const AZ::Vector2& position, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual float GetHeightFromFloats(
float x, float y, Sampler sampler = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Returns true if there's a hole at location x,y.
//! Also returns true if there's no terrain data at location x,y.
virtual bool GetIsHole(const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
virtual bool GetIsHoleFromVector2(const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
// Given an XY coordinate, return the surface normal.
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a
//! terrain HOLE then *terrainExistsPtr will be set to false,
//! otherwise *terrainExistsPtr will be set to true.
virtual AZ::Vector3 GetNormal(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual AZ::Vector3 GetNormalFromVector2(
const AZ::Vector2& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual AZ::Vector3 GetNormalFromFloats(
float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Given an XY coordinate, return the max surface type and weight. //! Given an XY coordinate, return the max surface type and weight.
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false, //! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false,
//! otherwise *terrainExistsPtr will be set to true. //! otherwise *terrainExistsPtr will be set to true.
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromVector2(
const AZ::Vector2& inPosition, Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0;
virtual SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(
float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore //! Given an XY coordinate, return the set of surface types and weights. The Vector3 input position version is defined to ignore
//! the input Z value. //! the input Z value.
virtual void GetSurfaceWeights( virtual void GetSurfaceWeights(
const AZ::Vector3& inPosition, const AZ::Vector3& inPosition,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT, Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0; bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfaceWeightsFromVector2( virtual void GetSurfaceWeightsFromVector2(
const AZ::Vector2& inPosition, const AZ::Vector2& inPosition,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT, Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0; bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfaceWeightsFromFloats( virtual void GetSurfaceWeightsFromFloats(
float x, float x,
float y, float y,
SurfaceData::OrderedSurfaceTagWeightSet& outSurfaceWeights, SurfaceData::SurfaceTagWeightList& outSurfaceWeights,
Sampler sampleFilter = Sampler::DEFAULT, Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0; bool* terrainExistsPtr = nullptr) const = 0;
//! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats. //! Convenience function for low level systems that can't do a reverse lookup from Crc to string. Everyone else should use GetMaxSurfaceWeight or GetMaxSurfaceWeightFromFloats.
//! Not available in the behavior context. //! Not available in the behavior context.
//! Returns nullptr if the position is inside a hole or outside of the terrain boundaries. //! Returns nullptr if the position is inside a hole or outside of the terrain boundaries.
virtual const char * GetMaxSurfaceName(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; virtual const char* GetMaxSurfaceName(
const AZ::Vector3& position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0;
//! Returns true if there's a hole at location x,y.
//! Also returns true if there's no terrain data at location x,y.
virtual bool GetIsHoleFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR) const = 0;
// Given an XY coordinate, return the surface normal. //! Given an XY coordinate, return all terrain information at that location. The Vector3 input position version is defined
//! @terrainExists: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will be set to false, //! to ignore the input Z value.
//! otherwise *terrainExistsPtr will be set to true. virtual void GetSurfacePoint(
virtual AZ::Vector3 GetNormal(AZ::Vector3 position, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; const AZ::Vector3& inPosition,
virtual AZ::Vector3 GetNormalFromFloats(float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const = 0; SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfacePointFromVector2(
const AZ::Vector2& inPosition,
SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
virtual void GetSurfacePointFromFloats(
float x,
float y,
SurfaceData::SurfacePoint& outSurfacePoint,
Sampler sampleFilter = Sampler::DEFAULT,
bool* terrainExistsPtr = nullptr) const = 0;
}; };
using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>; using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>;
@ -169,6 +165,10 @@ namespace AzFramework
} }
}; };
using TerrainDataNotificationBus = AZ::EBus<TerrainDataNotifications>; using TerrainDataNotificationBus = AZ::EBus<TerrainDataNotifications>;
} // namespace Terrain
} //namespace Terrain
} // namespace AzFramework } // namespace AzFramework
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(AzFramework::Terrain::TerrainDataRequests::Sampler, "{D29BB6D7-3006-4114-858D-355EAA256B86}");
} // namespace AZ

@ -252,7 +252,6 @@ set(FILES
Physics/Shape.h Physics/Shape.h
Physics/ShapeConfiguration.h Physics/ShapeConfiguration.h
Physics/ShapeConfiguration.cpp Physics/ShapeConfiguration.cpp
Physics/HeightfieldProviderBus.h
Physics/SystemBus.h Physics/SystemBus.h
Physics/ColliderComponentBus.h Physics/ColliderComponentBus.h
Physics/RagdollPhysicsBus.h Physics/RagdollPhysicsBus.h
@ -301,6 +300,8 @@ set(FILES
Spawnable/SpawnableMonitor.cpp Spawnable/SpawnableMonitor.cpp
Spawnable/SpawnableSystemComponent.h Spawnable/SpawnableSystemComponent.h
Spawnable/SpawnableSystemComponent.cpp Spawnable/SpawnableSystemComponent.cpp
SurfaceData/SurfaceData.h
SurfaceData/SurfaceData.cpp
Terrain/TerrainDataRequestBus.h Terrain/TerrainDataRequestBus.h
Terrain/TerrainDataRequestBus.cpp Terrain/TerrainDataRequestBus.cpp
Thermal/ThermalInfo.h Thermal/ThermalInfo.h

@ -28,4 +28,21 @@ namespace AzQtComponents
return scaledPixmap; return scaledPixmap;
} }
QPixmap CropPixmapForScreenDpi(
QPixmap pixmap, QScreen* screen, QRect rect)
{
qreal screenDpiFactor = QHighDpiScaling::factor(screen);
pixmap.setDevicePixelRatio(screenDpiFactor);
QRect cropRect(
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.left()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.top()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.width()) * screenDpiFactor),
aznumeric_cast<int>(aznumeric_cast<qreal>(rect.height()) * screenDpiFactor)
);
QPixmap croppedPixmap = pixmap.copy(cropRect);
return croppedPixmap;
}
} }

@ -11,9 +11,11 @@
#include <AzQtComponents/AzQtComponentsAPI.h> #include <AzQtComponents/AzQtComponentsAPI.h>
#include <QPixmap> #include <QPixmap>
#include <QRect>
#include <QScreen> #include <QScreen>
namespace AzQtComponents namespace AzQtComponents
{ {
AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode); AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode);
AZ_QT_COMPONENTS_API QPixmap CropPixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QRect rect);
}; // namespace AzQtComponents }; // namespace AzQtComponents

@ -36,6 +36,10 @@ namespace AzToolsFramework
//! the entity type. //! the entity type.
virtual AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EntityType entityType) = 0; virtual AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EntityType entityType) = 0;
//! Return a list of type ids for components that match the required services filter,
//! and don't conflict with any of the incompatible services filter
virtual AZStd::vector<AZ::Uuid> FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter) = 0;
//! Finds the component names from their type ids //! Finds the component names from their type ids
virtual AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) = 0; virtual AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) = 0;

@ -15,6 +15,7 @@
#include <AzToolsFramework/ToolsComponents/EditorDisabledCompositionBus.h> #include <AzToolsFramework/ToolsComponents/EditorDisabledCompositionBus.h>
#include <AzToolsFramework/ToolsComponents/EditorPendingCompositionBus.h> #include <AzToolsFramework/ToolsComponents/EditorPendingCompositionBus.h>
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h> #include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h> #include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h> #include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
@ -75,6 +76,7 @@ namespace AzToolsFramework
serializeContext->Class<EditorComponentAPIComponent, AZ::Component>(); serializeContext->Class<EditorComponentAPIComponent, AZ::Component>();
serializeContext->RegisterGenericType<AZStd::vector<AZ::EntityComponentIdPair>>(); serializeContext->RegisterGenericType<AZStd::vector<AZ::EntityComponentIdPair>>();
serializeContext->RegisterGenericType<AZStd::vector<AZ::ComponentServiceType>>();
} }
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
@ -99,6 +101,7 @@ namespace AzToolsFramework
->Attribute(AZ::Script::Attributes::Module, "editor") ->Attribute(AZ::Script::Attributes::Module, "editor")
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Event("FindComponentTypeIdsByEntityType", &EditorComponentAPIRequests::FindComponentTypeIdsByEntityType) ->Event("FindComponentTypeIdsByEntityType", &EditorComponentAPIRequests::FindComponentTypeIdsByEntityType)
->Event("FindComponentTypeIdsByService", &EditorComponentAPIRequests::FindComponentTypeIdsByService)
->Event("FindComponentTypeNames", &EditorComponentAPIRequests::FindComponentTypeNames) ->Event("FindComponentTypeNames", &EditorComponentAPIRequests::FindComponentTypeNames)
->Event("BuildComponentTypeNameListByEntityType", &EditorComponentAPIRequests::BuildComponentTypeNameListByEntityType) ->Event("BuildComponentTypeNameListByEntityType", &EditorComponentAPIRequests::BuildComponentTypeNameListByEntityType)
->Event("AddComponentsOfType", &EditorComponentAPIRequests::AddComponentsOfType) ->Event("AddComponentsOfType", &EditorComponentAPIRequests::AddComponentsOfType)
@ -216,6 +219,33 @@ namespace AzToolsFramework
return foundTypeIds; return foundTypeIds;
} }
AZStd::vector<AZ::Uuid> EditorComponentAPIComponent::FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter)
{
AZStd::vector<AZ::Uuid> foundTypeIds;
m_serializeContext->EnumerateDerived<AZ::Component>(
[&foundTypeIds, serviceFilter, incompatibleServiceFilter](const AZ::SerializeContext::ClassData* componentClass, const AZ::Uuid& knownType) -> bool
{
AZ_UNUSED(knownType);
if (componentClass->m_editData)
{
// If none of the required services are offered by this component, or the component
// can not be added by the user, skip to the next component
if (!OffersRequiredServices(componentClass, serviceFilter, incompatibleServiceFilter))
{
return true;
}
foundTypeIds.push_back(componentClass->m_typeId);
}
return true;
});
return foundTypeIds;
}
AZStd::vector<AZStd::string> EditorComponentAPIComponent::FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) AZStd::vector<AZStd::string> EditorComponentAPIComponent::FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds)
{ {
AZStd::vector<AZStd::string> foundTypeNames; AZStd::vector<AZStd::string> foundTypeNames;

@ -35,6 +35,7 @@ namespace AzToolsFramework
// EditorComponentAPIBus ... // EditorComponentAPIBus ...
AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EditorComponentAPIRequests::EntityType entityType) override; AZStd::vector<AZ::Uuid> FindComponentTypeIdsByEntityType(const AZStd::vector<AZStd::string>& componentTypeNames, EditorComponentAPIRequests::EntityType entityType) override;
AZStd::vector<AZ::Uuid> FindComponentTypeIdsByService(const AZStd::vector<AZ::ComponentServiceType>& serviceFilter, const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter) override;
AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) override; AZStd::vector<AZStd::string> FindComponentTypeNames(const AZ::ComponentTypeList& componentTypeIds) override;
AZStd::vector<AZStd::string> BuildComponentTypeNameListByEntityType(EditorComponentAPIRequests::EntityType entityType) override; AZStd::vector<AZStd::string> BuildComponentTypeNameListByEntityType(EditorComponentAPIRequests::EntityType entityType) override;

@ -271,6 +271,68 @@ namespace AzToolsFramework
return editorComponentBaseComponent; return editorComponentBaseComponent;
} }
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
)
{
AZ_Assert(componentClass, "Component class must not be null");
if (!componentClass)
{
return false;
}
AZ::ComponentDescriptor* componentDescriptor = nullptr;
AZ::ComponentDescriptorBus::EventResult(
componentDescriptor, componentClass->m_typeId, &AZ::ComponentDescriptor::GetDescriptor);
if (!componentDescriptor)
{
return false;
}
// If no services are provided, this function returns true
if (serviceFilter.empty())
{
return true;
}
AZ::ComponentDescriptor::DependencyArrayType providedServices;
componentDescriptor->GetProvidedServices(providedServices, nullptr);
//reject this component if it does not offer any of the required services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
serviceFilter.begin(),
serviceFilter.end()) == providedServices.end())
{
return false;
}
//reject this component if it does offer any of the incompatible services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
incompatibleServiceFilter.begin(),
incompatibleServiceFilter.end()) != providedServices.end())
{
return false;
}
return true;
}
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
)
{
const AZStd::vector<AZ::ComponentServiceType> incompatibleServices;
return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices);
}
bool ShouldInspectorShowComponent(const AZ::Component* component) bool ShouldInspectorShowComponent(const AZ::Component* component)
{ {
if (!component) if (!component)

@ -105,6 +105,16 @@ namespace AzToolsFramework
AZ::ComponentDescriptor* GetComponentDescriptor(const AZ::Component* component); AZ::ComponentDescriptor* GetComponentDescriptor(const AZ::Component* component);
Components::EditorComponentDescriptor* GetEditorComponentDescriptor(const AZ::Component* component); Components::EditorComponentDescriptor* GetEditorComponentDescriptor(const AZ::Component* component);
Components::EditorComponentBase* GetEditorComponent(AZ::Component* component); Components::EditorComponentBase* GetEditorComponent(AZ::Component* component);
// Returns true if the given component provides at least one of the services specified or no services are provided
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
);
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
);
/// Return true if the editor should show this component to users, /// Return true if the editor should show this component to users,
/// false if the component should be hidden from users. /// false if the component should be hidden from users.

@ -16,6 +16,7 @@
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h> #include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
#include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h> #include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h>
#include <AzToolsFramework/Prefab/PrefabFocusUndo.h> #include <AzToolsFramework/Prefab/PrefabFocusUndo.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
namespace AzToolsFramework::Prefab namespace AzToolsFramework::Prefab
{ {
@ -79,7 +80,7 @@ namespace AzToolsFramework::Prefab
auto editUndo = aznew PrefabFocusUndo("Edit Prefab"); auto editUndo = aznew PrefabFocusUndo("Edit Prefab");
editUndo->Capture(entityId); editUndo->Capture(entityId);
editUndo->SetParent(undoBatch.GetUndoBatch()); editUndo->SetParent(undoBatch.GetUndoBatch());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo); FocusOnPrefabInstanceOwningEntityId(entityId);
} }
return AZ::Success(); return AZ::Success();
@ -94,9 +95,7 @@ namespace AzToolsFramework::Prefab
InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index]; InstanceOptionalReference focusedInstance = m_instanceFocusHierarchy[index];
FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId()); return FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId());
return AZ::Success();
} }
PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId)
@ -255,7 +254,7 @@ namespace AzToolsFramework::Prefab
void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name) void PrefabFocusHandler::OnEntityInfoUpdatedName(AZ::EntityId entityId, [[maybe_unused]]const AZStd::string& name)
{ {
// Determine if the entityId is the container for any of the instances in the vector // Determine if the entityId is the container for any of the instances in the vector.
auto result = AZStd::find_if( auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(), m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[entityId](const InstanceOptionalReference& instance) [entityId](const InstanceOptionalReference& instance)
@ -279,6 +278,25 @@ namespace AzToolsFramework::Prefab
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged); PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
} }
void PrefabFocusHandler::OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, [[maybe_unused]] bool status)
{
// Determine if the templateId matches any of the instances in the vector.
auto result = AZStd::find_if(
m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end(),
[templateId](const InstanceOptionalReference& instance)
{
return (instance->get().GetTemplateId() == templateId);
}
);
if (result != m_instanceFocusHierarchy.end())
{
// Refresh the path and notify changes.
RefreshInstanceFocusPath();
PrefabFocusNotificationBus::Broadcast(&PrefabFocusNotifications::OnPrefabFocusChanged);
}
}
void PrefabFocusHandler::RefreshInstanceFocusList() void PrefabFocusHandler::RefreshInstanceFocusList()
{ {
m_instanceFocusHierarchy.clear(); m_instanceFocusHierarchy.clear();
@ -293,17 +311,42 @@ namespace AzToolsFramework::Prefab
currentInstance = currentInstance->get().GetParentInstance(); currentInstance = currentInstance->get().GetParentInstance();
} }
// Invert the vector, since we need the top instance to be at index 0 // Invert the vector, since we need the top instance to be at index 0.
AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end()); AZStd::reverse(m_instanceFocusHierarchy.begin(), m_instanceFocusHierarchy.end());
} }
void PrefabFocusHandler::RefreshInstanceFocusPath() void PrefabFocusHandler::RefreshInstanceFocusPath()
{ {
auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
m_instanceFocusPath.clear(); m_instanceFocusPath.clear();
size_t index = 0;
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy) for (const InstanceOptionalReference& instance : m_instanceFocusHierarchy)
{ {
m_instanceFocusPath.Append(instance->get().GetContainerEntity()->get().GetName()); AZStd::string prefabName;
if (index < maxIndex)
{
// Get the filename without the extension (stem).
prefabName = instance->get().GetTemplateSourcePath().Stem().Native();
}
else
{
// Get the full filename.
prefabName = instance->get().GetTemplateSourcePath().Filename().Native();
}
if (prefabSystemComponentInterface->IsTemplateDirty(instance->get().GetTemplateId()))
{
prefabName += "*";
}
m_instanceFocusPath.Append(prefabName);
++index;
} }
} }

@ -64,8 +64,9 @@ namespace AzToolsFramework::Prefab
void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override; void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& name) override;
// PrefabPublicNotifications overrides ... // PrefabPublicNotifications overrides ...
void OnPrefabInstancePropagationEnd(); void OnPrefabInstancePropagationEnd() override;
void OnPrefabTemplateDirtyFlagUpdated(TemplateId templateId, bool status) override;
private: private:
PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance); PrefabFocusOperationResult FocusOnPrefabInstance(InstanceOptionalReference focusedInstance);
void RefreshInstanceFocusList(); void RefreshInstanceFocusList();

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <AzCore/EBus/EBus.h> #include <AzCore/EBus/EBus.h>
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
namespace AzToolsFramework namespace AzToolsFramework
{ {
@ -22,6 +23,9 @@ namespace AzToolsFramework
virtual void OnPrefabInstancePropagationBegin() {} virtual void OnPrefabInstancePropagationBegin() {}
virtual void OnPrefabInstancePropagationEnd() {} virtual void OnPrefabInstancePropagationEnd() {}
virtual void OnPrefabTemplateDirtyFlagUpdated(
[[maybe_unused]] TemplateId templateId, [[maybe_unused]] bool status) {}
}; };
using PrefabPublicNotificationBus = AZ::EBus<PrefabPublicNotifications>; using PrefabPublicNotificationBus = AZ::EBus<PrefabPublicNotifications>;

@ -185,7 +185,7 @@ namespace AzToolsFramework
if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal) if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal)
{ {
templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator());
templateToUpdate->get().MarkAsDirty(true); SetTemplateDirtyFlag(templateId, true);
PropagateTemplateChanges(templateId); PropagateTemplateChanges(templateId);
} }
} }
@ -813,11 +813,12 @@ namespace AzToolsFramework
void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty) void PrefabSystemComponent::SetTemplateDirtyFlag(TemplateId templateId, bool dirty)
{ {
auto templateRef = FindTemplate(templateId); if (auto templateReference = FindTemplate(templateId); templateReference.has_value())
if (templateRef.has_value())
{ {
templateRef->get().MarkAsDirty(dirty); templateReference->get().MarkAsDirty(dirty);
PrefabPublicNotificationBus::Broadcast(
&PrefabPublicNotificationBus::Events::OnPrefabTemplateDirtyFlagUpdated, templateId, dirty);
} }
} }

@ -12,6 +12,7 @@
#include <AzCore/Component/Component.h> #include <AzCore/Component/Component.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h> #include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags<Qt::AlignmentFlag>' needs to have dll-interface to be used by clients of class 'QLayoutItem' AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QLayoutItem::align': class 'QFlags<Qt::AlignmentFlag>' needs to have dll-interface to be used by clients of class 'QLayoutItem'
#include <AzToolsFramework/UI/SearchWidget/SearchCriteriaWidget.hxx> #include <AzToolsFramework/UI/SearchWidget/SearchCriteriaWidget.hxx>
AZ_POP_DISABLE_WARNING AZ_POP_DISABLE_WARNING
@ -20,67 +21,6 @@ namespace AzToolsFramework
{ {
namespace ComponentPaletteUtil namespace ComponentPaletteUtil
{ {
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
)
{
AZ_Assert(componentClass, "Component class must not be null");
if (!componentClass)
{
return false;
}
AZ::ComponentDescriptor* componentDescriptor = nullptr;
EBUS_EVENT_ID_RESULT(componentDescriptor, componentClass->m_typeId, AZ::ComponentDescriptorBus, GetDescriptor);
if (!componentDescriptor)
{
return false;
}
// If no services are provided, this function returns true
if (serviceFilter.empty())
{
return true;
}
AZ::ComponentDescriptor::DependencyArrayType providedServices;
componentDescriptor->GetProvidedServices(providedServices, nullptr);
//reject this component if it does not offer any of the required services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
serviceFilter.begin(),
serviceFilter.end()) == providedServices.end())
{
return false;
}
//reject this component if it does offer any of the incompatible services
if (AZStd::find_first_of(
providedServices.begin(),
providedServices.end(),
incompatibleServiceFilter.begin(),
incompatibleServiceFilter.end()) != providedServices.end())
{
return false;
}
return true;
}
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
)
{
const AZStd::vector<AZ::ComponentServiceType> incompatibleServices;
return OffersRequiredServices(componentClass, serviceFilter, incompatibleServices);
}
bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass) bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass)
{ {
AZ_Assert(componentClass, "component class must not be null"); AZ_Assert(componentClass, "component class must not be null");

@ -26,18 +26,6 @@ namespace AzToolsFramework
using ComponentIconTable = AZStd::map<const AZ::SerializeContext::ClassData*, QString>; using ComponentIconTable = AZStd::map<const AZ::SerializeContext::ClassData*, QString>;
// Returns true if the given component provides at least one of the services specified or no services are provided
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter,
const AZStd::vector<AZ::ComponentServiceType>& incompatibleServiceFilter
);
bool OffersRequiredServices(
const AZ::SerializeContext::ClassData* componentClass,
const AZStd::vector<AZ::ComponentServiceType>& serviceFilter
);
// Returns true if the given component is addable by the user // Returns true if the given component is addable by the user
bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass); bool IsAddableByUser(const AZ::SerializeContext::ClassData* componentClass);

@ -10,6 +10,8 @@
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h> #include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
#include <QTimer>
namespace AzToolsFramework::Prefab namespace AzToolsFramework::Prefab
{ {
PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler() PrefabViewportFocusPathHandler::PrefabViewportFocusPathHandler()
@ -47,6 +49,9 @@ namespace AzToolsFramework::Prefab
[&](const QString&, int linkIndex) [&](const QString&, int linkIndex)
{ {
m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex); m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex);
// Manually refresh path
QTimer::singleShot(0, [&]() { OnPrefabFocusChanged(); });
} }
); );

@ -22,6 +22,7 @@
#include <AzToolsFramework/Application/ToolsApplication.h> #include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h> #include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h> #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/UnitTest/ToolsTestApplication.h> #include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
// Inspector Test Includes // Inspector Test Includes
@ -313,17 +314,17 @@ namespace UnitTest
AZ_TEST_ASSERT(testComponent1_ProvidedServices.size() == 1); AZ_TEST_ASSERT(testComponent1_ProvidedServices.size() == 1);
const AZ::SerializeContext::ClassData* testComponent1_ClassData = context->FindClassData(testComponent1_typeId); const AZ::SerializeContext::ClassData* testComponent1_ClassData = context->FindClassData(testComponent1_typeId);
EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices)); EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent1_ProvidedServices));
// Verify that OffersRequiredServices returns when given services provided by a different component // Verify that OffersRequiredServices returns when given services provided by a different component
AZ::ComponentDescriptor::DependencyArrayType testComponent2_ProvidedServices; AZ::ComponentDescriptor::DependencyArrayType testComponent2_ProvidedServices;
Inspector_TestComponent2::GetProvidedServices(testComponent2_ProvidedServices); Inspector_TestComponent2::GetProvidedServices(testComponent2_ProvidedServices);
AZ_TEST_ASSERT(testComponent2_ProvidedServices.size() == 1); AZ_TEST_ASSERT(testComponent2_ProvidedServices.size() == 1);
AZ_TEST_ASSERT(testComponent1_ProvidedServices != testComponent2_ProvidedServices); AZ_TEST_ASSERT(testComponent1_ProvidedServices != testComponent2_ProvidedServices);
EXPECT_FALSE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices)); EXPECT_FALSE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, testComponent2_ProvidedServices));
// verify that OffersRequiredServices returns true when provided with an empty list of services // verify that OffersRequiredServices returns true when provided with an empty list of services
EXPECT_TRUE(AzToolsFramework::ComponentPaletteUtil::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType())); EXPECT_TRUE(AzToolsFramework::OffersRequiredServices(testComponent1_ClassData, AZ::ComponentDescriptor::DependencyArrayType()));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// TEST IsAddableByUser() // TEST IsAddableByUser()

@ -8,9 +8,11 @@
#include <DownloadController.h> #include <DownloadController.h>
#include <DownloadWorker.h> #include <DownloadWorker.h>
#include <PythonBindings.h>
#include <QMessageBox> #include <AzCore/std/algorithm.h>
#include <QMessageBox>
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
@ -46,6 +48,24 @@ namespace O3DE::ProjectManager
} }
} }
void DownloadController::CancelGemDownload(const QString& gemName)
{
auto findResult = AZStd::find(m_gemNames.begin(), m_gemNames.end(), gemName);
if (findResult != m_gemNames.end())
{
if (findResult == m_gemNames.begin())
{
// HandleResults will remove the gem upon cancelling
PythonBindingsInterface::Get()->CancelDownload();
}
else
{
m_gemNames.erase(findResult);
}
}
}
void DownloadController::UpdateUIProgress(int progress) void DownloadController::UpdateUIProgress(int progress)
{ {
m_lastProgress = progress; m_lastProgress = progress;
@ -75,10 +95,4 @@ namespace O3DE::ProjectManager
m_workerThread.wait(); m_workerThread.wait();
} }
} }
void DownloadController::HandleCancel()
{
m_workerThread.quit();
emit Done(false);
}
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -27,7 +27,8 @@ namespace O3DE::ProjectManager
explicit DownloadController(QWidget* parent = nullptr); explicit DownloadController(QWidget* parent = nullptr);
~DownloadController(); ~DownloadController();
void AddGemDownload(const QString& m_gemName); void AddGemDownload(const QString& gemName);
void CancelGemDownload(const QString& gemName);
bool IsDownloadQueueEmpty() bool IsDownloadQueueEmpty()
{ {
@ -54,7 +55,6 @@ namespace O3DE::ProjectManager
public slots: public slots:
void UpdateUIProgress(int progress); void UpdateUIProgress(int progress);
void HandleResults(const QString& result); void HandleResults(const QString& result);
void HandleCancel();
signals: signals:
void StartGemDownload(const QString& gemName); void StartGemDownload(const QString& gemName);

@ -155,6 +155,11 @@ namespace O3DE::ProjectManager
update(); update();
} }
void CartOverlayWidget::OnCancelDownloadActivated(const QString& gemName)
{
m_downloadController->CancelGemDownload(gemName);
}
void CartOverlayWidget::CreateDownloadSection() void CartOverlayWidget::CreateDownloadSection()
{ {
QWidget* widget = new QWidget(); QWidget* widget = new QWidget();
@ -235,7 +240,9 @@ namespace O3DE::ProjectManager
nameProgressLayout->addWidget(progress); nameProgressLayout->addWidget(progress);
QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
nameProgressLayout->addSpacerItem(spacer); nameProgressLayout->addSpacerItem(spacer);
QLabel* cancelText = new QLabel(tr("Cancel")); QLabel* cancelText = new QLabel(QString("<a href=\"%1\">Cancel</a>").arg(downloadQueue[downloadingGemNumber]));
cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated);
nameProgressLayout->addWidget(cancelText); nameProgressLayout->addWidget(cancelText);
downloadingItemLayout->addLayout(nameProgressLayout); downloadingItemLayout->addLayout(nameProgressLayout);
QProgressBar* downloadProgessBar = new QProgressBar(); QProgressBar* downloadProgessBar = new QProgressBar();

@ -41,6 +41,7 @@ namespace O3DE::ProjectManager
using GetTagIndicesCallback = AZStd::function<QVector<QModelIndex>()>; using GetTagIndicesCallback = AZStd::function<QVector<QModelIndex>()>;
void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices); void CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices);
void CreateDownloadSection(); void CreateDownloadSection();
void OnCancelDownloadActivated(const QString& link);
QVBoxLayout* m_layout = nullptr; QVBoxLayout* m_layout = nullptr;
GemModel* m_gemModel = nullptr; GemModel* m_gemModel = nullptr;

@ -223,6 +223,7 @@ namespace RedirectOutput
} }
} // namespace RedirectOutput } // namespace RedirectOutput
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath) PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
@ -1120,18 +1121,29 @@ namespace O3DE::ProjectManager
AZ::Outcome<void, AZStd::string> PythonBindings::DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) AZ::Outcome<void, AZStd::string> PythonBindings::DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback)
{ {
// This process is currently limited to download a single gem at a time.
bool downloadSucceeded = false; bool downloadSucceeded = false;
m_requestCancelDownload = false;
auto result = ExecuteWithLockErrorHandling( auto result = ExecuteWithLockErrorHandling(
[&] [&]
{ {
auto downloadResult = m_download.attr("download_gem")( auto downloadResult = m_download.attr("download_gem")(
QString_To_Py_String(gemName), // gem name QString_To_Py_String(gemName), // gem name
pybind11::none(), // destination path pybind11::none(), // destination path
false// skip auto register false, // skip auto register
pybind11::cpp_function(
[this, gemProgressCallback](int progress)
{
gemProgressCallback(progress);
return m_requestCancelDownload;
}) // Callback for download progress and cancelling
); );
downloadSucceeded = (downloadResult.cast<int>() == 0); downloadSucceeded = (downloadResult.cast<int>() == 0);
}); });
if (!result.IsSuccess()) if (!result.IsSuccess())
{ {
return result; return result;
@ -1143,4 +1155,9 @@ namespace O3DE::ProjectManager
return AZ::Success(); return AZ::Success();
} }
void PythonBindings::CancelDownload()
{
m_requestCancelDownload = true;
}
} }

@ -63,6 +63,7 @@ namespace O3DE::ProjectManager
bool RemoveGemRepo(const QString& repoUri) override; bool RemoveGemRepo(const QString& repoUri) override;
AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() override; AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() override;
AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) override; AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) override;
void CancelDownload() override;
private: private:
AZ_DISABLE_COPY_MOVE(PythonBindings); AZ_DISABLE_COPY_MOVE(PythonBindings);
@ -91,5 +92,7 @@ namespace O3DE::ProjectManager
pybind11::handle m_editProjectProperties; pybind11::handle m_editProjectProperties;
pybind11::handle m_download; pybind11::handle m_download;
pybind11::handle m_pathlib; pybind11::handle m_pathlib;
bool m_requestCancelDownload = false;
}; };
} }

@ -196,7 +196,18 @@ namespace O3DE::ProjectManager
*/ */
virtual AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() = 0; virtual AZ::Outcome<QVector<GemRepoInfo>, AZStd::string> GetAllGemRepoInfos() = 0;
/**
* Downloads and registers a Gem.
* @param gemName the name of the Gem to download
* @param gemProgressCallback a callback function that is called with an int percentage download value
* @return an outcome with a string error message on failure.
*/
virtual AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) = 0; virtual AZ::Outcome<void, AZStd::string> DownloadGem(const QString& gemName, std::function<void(int)> gemProgressCallback) = 0;
/**
* Cancels the current download.
*/
virtual void CancelDownload() = 0;
}; };
using PythonBindingsInterface = AZ::Interface<IPythonBindings>; using PythonBindingsInterface = AZ::Interface<IPythonBindings>;

@ -81,7 +81,7 @@ namespace AZ
// Register Shader Asset Builder // Register Shader Asset Builder
AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor;
shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder";
shaderAssetBuilderDescriptor.m_version = 105; // [AZSL] Changing inlineConstant to rootConstant keyword work. shaderAssetBuilderDescriptor.m_version = 107; // Required .azsl extension in .shader file references
// .shader file changes trigger rebuilds // .shader file changes trigger rebuilds
shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
shaderAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderAssetBuilder>(); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderAssetBuilder>();

@ -151,11 +151,11 @@ namespace AZ
void ShaderAssetBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const void ShaderAssetBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const
{ {
AZStd::string fullPath; AZStd::string shaderAssetSourceFileFullPath;
AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullPath, true); AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), shaderAssetSourceFileFullPath, true);
ShaderBuilderUtility::IncludedFilesParser includedFilesParser; ShaderBuilderUtility::IncludedFilesParser includedFilesParser;
AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for Shader \"%s\"\n", fullPath.data()); AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for Shader \"%s\"\n", shaderAssetSourceFileFullPath.data());
// Used to synchronize versions of the ShaderAsset and ShaderVariantTreeAsset, especially during hot-reload. // Used to synchronize versions of the ShaderAsset and ShaderVariantTreeAsset, especially during hot-reload.
// Note it's probably important for this to be set once outside the platform loop so every platform's ShaderAsset // Note it's probably important for this to be set once outside the platform loop so every platform's ShaderAsset
@ -166,7 +166,7 @@ namespace AZ
// Need to get the name of the azsl file from the .shader source asset, to be able to declare a dependency to SRG Layout Job. // Need to get the name of the azsl file from the .shader source asset, to be able to declare a dependency to SRG Layout Job.
// and the macro options to preprocess. // and the macro options to preprocess.
auto descriptorParseOutcome = ShaderBuilderUtility::LoadShaderDataJson(fullPath); auto descriptorParseOutcome = ShaderBuilderUtility::LoadShaderDataJson(shaderAssetSourceFileFullPath);
if (!descriptorParseOutcome.IsSuccess()) if (!descriptorParseOutcome.IsSuccess())
{ {
AZ_Error( AZ_Error(
@ -178,7 +178,7 @@ namespace AZ
RPI::ShaderSourceData shaderSourceData = descriptorParseOutcome.TakeValue(); RPI::ShaderSourceData shaderSourceData = descriptorParseOutcome.TakeValue();
AZStd::string azslFullPath; AZStd::string azslFullPath;
ShaderBuilderUtility::GetAbsolutePathToAzslFile(fullPath, shaderSourceData.m_source, azslFullPath); ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderAssetSourceFileFullPath, shaderSourceData.m_source, azslFullPath);
{ {
// Add the AZSL as source dependency // Add the AZSL as source dependency
@ -191,9 +191,9 @@ namespace AZ
{ {
AZ_Error( AZ_Error(
ShaderAssetBuilderName, false, "Shader program listed as the source entry does not exist: %s.", azslFullPath.c_str()); ShaderAssetBuilderName, false, "Shader program listed as the source entry does not exist: %s.", azslFullPath.c_str());
// Treat as success, so when the azsl file shows up the AP will try to recompile. // Even though there was an error here, don't stop, because we need to report the SourceFileDependency so when the azsl
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; // file shows up the AP will try to recompile. We will go ahead and create the job anyway, and then ProcessJob can
return; // report the failure.
} }
GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName); GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName);
@ -229,7 +229,7 @@ namespace AZ
} // for all request.m_enabledPlatforms } // for all request.m_enabledPlatforms
AZ_TracePrintf( AZ_TracePrintf(
ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", fullPath.c_str(), ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", shaderAssetSourceFileFullPath.c_str(),
AZStd::GetTimeNowMicroSecond() - shaderAssetBuildTimestamp); AZStd::GetTimeNowMicroSecond() - shaderAssetBuildTimestamp);
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;

@ -70,11 +70,11 @@ namespace AZ
return AZ::Success(shaderSourceData); return AZ::Success(shaderSourceData);
} }
void GetAbsolutePathToAzslFile(const AZStd::string& shaderTemplatePathAndFile, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteAzslPath) void GetAbsolutePathToAzslFile(const AZStd::string& shaderSourceFileFullPath, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteAzslPath)
{ {
AZStd::string sourcePath; AZStd::string sourcePath;
AzFramework::StringFunc::Path::GetFullPath(shaderTemplatePathAndFile.data(), sourcePath); AzFramework::StringFunc::Path::GetFullPath(shaderSourceFileFullPath.c_str(), sourcePath);
AzFramework::StringFunc::Path::Normalize(specifiedShaderPathAndName); AzFramework::StringFunc::Path::Normalize(specifiedShaderPathAndName);
bool shaderNameHasPath = (specifiedShaderPathAndName.find(AZ_CORRECT_FILESYSTEM_SEPARATOR) != AZStd::string::npos); bool shaderNameHasPath = (specifiedShaderPathAndName.find(AZ_CORRECT_FILESYSTEM_SEPARATOR) != AZStd::string::npos);
@ -82,15 +82,27 @@ namespace AZ
// Join will handle overlapping directory structures for us // Join will handle overlapping directory structures for us
AzFramework::StringFunc::Path::Join(sourcePath.data(), specifiedShaderPathAndName.data(), absoluteAzslPath, shaderNameHasPath /* handle directory overlap? */, false /* be case insensitive? */); AzFramework::StringFunc::Path::Join(sourcePath.data(), specifiedShaderPathAndName.data(), absoluteAzslPath, shaderNameHasPath /* handle directory overlap? */, false /* be case insensitive? */);
AzFramework::StringFunc::Path::ReplaceExtension(absoluteAzslPath, "azsl"); // The builders used to automatically set the ".azsl" extension, but no more, because that would make the .shader file confusing to read.
// Here we just detect the issue and instruct the user what to change.
// (There's no need to return a failure code, the builder will eventually fail anyway when it can't find the file).
if (!IO::FileIOBase::GetInstance()->Exists(absoluteAzslPath.c_str()))
{
AZStd::string absoluteAzslPathWithForcedExtension = absoluteAzslPath;
AzFramework::StringFunc::Path::ReplaceExtension(absoluteAzslPathWithForcedExtension, "azsl");
if (IO::FileIOBase::GetInstance()->Exists(absoluteAzslPathWithForcedExtension.c_str()))
{
AZ_Error(ShaderBuilderUtilityName, false, "When the .shader file references a .azsl file, it must include the \".azsl\" extension.");
}
}
} }
AZStd::shared_ptr<ShaderFiles> PrepareSourceInput( AZStd::shared_ptr<ShaderFiles> PrepareSourceInput(
[[maybe_unused]] const char* builderName, [[maybe_unused]] const char* builderName,
const AZStd::string& shaderAssetSourcePath, const AZStd::string& shaderSourceFileFullPath,
RPI::ShaderSourceData& sourceAsset) RPI::ShaderSourceData& sourceAsset)
{ {
auto shaderAssetSourceFileParseOutput = ShaderBuilderUtility::LoadShaderDataJson(shaderAssetSourcePath); auto shaderAssetSourceFileParseOutput = ShaderBuilderUtility::LoadShaderDataJson(shaderSourceFileFullPath);
if (!shaderAssetSourceFileParseOutput.IsSuccess()) if (!shaderAssetSourceFileParseOutput.IsSuccess())
{ {
AZ_Error(builderName, false, "Failed to load/parse Shader Descriptor JSON: %s", shaderAssetSourceFileParseOutput.GetError().c_str()); AZ_Error(builderName, false, "Failed to load/parse Shader Descriptor JSON: %s", shaderAssetSourceFileParseOutput.GetError().c_str());
@ -100,7 +112,7 @@ namespace AZ
AZStd::shared_ptr<ShaderFiles> files(new ShaderFiles); AZStd::shared_ptr<ShaderFiles> files(new ShaderFiles);
const AZStd::string& specifiedAzslName = sourceAsset.m_source; const AZStd::string& specifiedAzslName = sourceAsset.m_source;
ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderAssetSourcePath, specifiedAzslName, files->m_azslSourceFullPath); ShaderBuilderUtility::GetAbsolutePathToAzslFile(shaderSourceFileFullPath, specifiedAzslName, files->m_azslSourceFullPath);
// specifiedAzslName may have a relative path on it so need to strip it // specifiedAzslName may have a relative path on it so need to strip it
AzFramework::StringFunc::Path::GetFileName(specifiedAzslName.c_str(), files->m_azslFileName); AzFramework::StringFunc::Path::GetFileName(specifiedAzslName.c_str(), files->m_azslFileName);

@ -33,12 +33,12 @@ namespace AZ
{ {
Outcome<RPI::ShaderSourceData, AZStd::string> LoadShaderDataJson(const AZStd::string& fullPathToJsonFile); Outcome<RPI::ShaderSourceData, AZStd::string> LoadShaderDataJson(const AZStd::string& fullPathToJsonFile);
void GetAbsolutePathToAzslFile(const AZStd::string& shaderTemplatePathAndFile, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteShaderPath); void GetAbsolutePathToAzslFile(const AZStd::string& shaderSourceFileFullPath, AZStd::string specifiedShaderPathAndName, AZStd::string& absoluteShaderPath);
//! Opens and read the .shader, returns expanded file paths //! Opens and read the .shader, returns expanded file paths
AZStd::shared_ptr<ShaderFiles> PrepareSourceInput( AZStd::shared_ptr<ShaderFiles> PrepareSourceInput(
const char* builderName, const char* builderName,
const AZStd::string& shaderAssetSourcePath, const AZStd::string& shaderSourceFileFullPath,
RPI::ShaderSourceData& sourceAsset); RPI::ShaderSourceData& sourceAsset);
namespace AzslSubProducts namespace AzslSubProducts

@ -0,0 +1,170 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldTemplate",
"PassClass": "NewDepthOfFieldParentPass",
"Slots": [
{
"Name": "Depth",
"SlotType": "Input"
},
{
"Name": "LightingBuffer",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
}
],
"PassRequests": [
{
"Name": "AutoFocus",
"TemplateName": "DepthOfFieldReadBackFocusDepthTemplate",
"Connections": [
{
"LocalSlot": "DepthInput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "Depth"
}
}
]
},
{
"Name": "Downsample",
"TemplateName": "NewDepthOfFieldDownsampleTemplate",
"Connections": [
{
"LocalSlot": "ColorInput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "LightingBuffer"
}
},
{
"LocalSlot": "DepthInput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "Depth"
}
}
]
},
{
"Name": "TileReduce",
"TemplateName": "NewDepthOfFieldTileReduceTemplate",
"Connections": [
{
"LocalSlot": "ColorAndCocInput",
"AttachmentRef": {
"Pass": "Downsample",
"Attachment": "OutputColorAndCoC"
}
}
]
},
{
"Name": "Tile3x3",
"TemplateName": "NewDepthOfFieldTile3x3Template",
"Connections": [
{
"LocalSlot": "Input",
"AttachmentRef": {
"Pass": "TileReduce",
"Attachment": "MinMaxCoC"
}
}
]
},
{
"Name": "Tile5x5",
"TemplateName": "NewDepthOfFieldTile3x3Template",
"Connections": [
{
"LocalSlot": "Input",
"AttachmentRef": {
"Pass": "Tile3x3",
"Attachment": "Output"
}
}
]
},
{
"Name": "LargeFilter",
"TemplateName": "NewDepthOfFieldFilterLargeTemplate",
"Connections": [
{
"LocalSlot": "ColorAndCoc",
"AttachmentRef": {
"Pass": "Downsample",
"Attachment": "OutputColorAndCoC"
}
},
{
"LocalSlot": "CocTile",
"AttachmentRef": {
"Pass": "Tile5x5",
"Attachment": "Output"
}
}
]
},
{
"Name": "SmallFilter",
"TemplateName": "NewDepthOfFieldFilterSmallTemplate",
"Connections": [
{
"LocalSlot": "ColorAndCoc",
"AttachmentRef": {
"Pass": "LargeFilter",
"Attachment": "OutputColorAndCoc"
}
},
{
"LocalSlot": "CocTile",
"AttachmentRef": {
"Pass": "Tile3x3",
"Attachment": "Output"
}
}
]
},
{
"Name": "Composite",
"TemplateName": "NewDepthOfFieldCompositeTemplate",
"Connections": [
{
"LocalSlot": "Depth",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "Depth"
}
},
{
"LocalSlot": "HalfResColorAndCoC",
"AttachmentRef": {
"Pass": "SmallFilter",
"Attachment": "OutputColorAndCoc"
}
},
{
"LocalSlot": "ColorInputOutput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "LightingBuffer"
}
}
]
}
]
}
}
}

@ -0,0 +1,37 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldCompositeTemplate",
"PassClass": "FullScreenTriangle",
"Slots": [
{
"Name": "Depth",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_fullResDimensions"
},
{
"Name": "HalfResColorAndCoC",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_halfResDimensions"
},
{
"Name": "ColorInputOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
}
],
"PassData": {
"$type": "FullscreenTrianglePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldComposite.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -0,0 +1,72 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldDownsampleTemplate",
"PassClass": "FullScreenTriangle",
"Slots": [
{
"Name": "ColorInput",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_inputDimensions"
},
{
"Name": "DepthInput",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"AspectFlags": [
"Depth"
]
}
},
{
"Name": "OutputColorAndCoC",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"ShaderImageDimensionsConstant": "m_outputDimensions",
"LoadStoreAction": {
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "OutputAttachment",
"SizeSource": {
"Source": {
"Pass": "This",
"Attachment": "ColorInput"
},
"Multipliers": {
"WidthMultiplier": 0.5,
"HeightMultiplier": 0.5
}
},
"ImageDescriptor": {
"Format": "R16G16B16A16_FLOAT"
}
}
],
"Connections": [
{
"LocalSlot": "OutputColorAndCoC",
"AttachmentRef": {
"Pass": "This",
"Attachment": "OutputAttachment"
}
}
],
"PassData": {
"$type": "FullscreenTrianglePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldDownsample.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -0,0 +1,62 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldFilterLargeTemplate",
"PassClass": "NewDepthOfFieldFilterPass",
"Slots": [
{
"Name": "ColorAndCoc",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_textureDimensions"
},
{
"Name": "CocTile",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "OutputColorAndCoc",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "OutputAttachment",
"SizeSource": {
"Source": {
"Pass": "This",
"Attachment": "ColorAndCoc"
}
},
"ImageDescriptor": {
"Format": "R16G16B16A16_FLOAT"
}
}
],
"Connections": [
{
"LocalSlot": "OutputColorAndCoc",
"AttachmentRef": {
"Pass": "This",
"Attachment": "OutputAttachment"
}
}
],
"PassData": {
"$type": "FullscreenTrianglePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldFilterLarge.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -0,0 +1,62 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldFilterSmallTemplate",
"PassClass": "NewDepthOfFieldFilterPass",
"Slots": [
{
"Name": "ColorAndCoc",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_textureDimensions"
},
{
"Name": "CocTile",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "OutputColorAndCoc",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "OutputAttachment",
"SizeSource": {
"Source": {
"Pass": "This",
"Attachment": "ColorAndCoc"
}
},
"ImageDescriptor": {
"Format": "R16G16B16A16_FLOAT"
}
}
],
"Connections": [
{
"LocalSlot": "OutputColorAndCoc",
"AttachmentRef": {
"Pass": "This",
"Attachment": "OutputAttachment"
}
}
],
"PassData": {
"$type": "FullscreenTrianglePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldFilterSmall.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -0,0 +1,57 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldTile3x3Template",
"PassClass": "FullScreenTriangle",
"Slots": [
{
"Name": "Input",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_textureDimensions"
},
{
"Name": "Output",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "OutputAttachment",
"SizeSource": {
"Source": {
"Pass": "This",
"Attachment": "Input"
}
},
"ImageDescriptor": {
"Format": "R16G16_SNORM"
}
}
],
"Connections": [
{
"LocalSlot": "Output",
"AttachmentRef": {
"Pass": "This",
"Attachment": "OutputAttachment"
}
}
],
"PassData": {
"$type": "FullscreenTrianglePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldTile3x3.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -0,0 +1,63 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "NewDepthOfFieldTileReduceTemplate",
"PassClass": "NewDepthOfFieldTileReducePass",
"Slots": [
{
"Name": "ColorAndCocInput",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_inputDimensions"
},
{
"Name": "MinMaxCoC",
"SlotType": "Output",
"ScopeAttachmentUsage": "Shader",
"ShaderImageDimensionsConstant": "m_outputDimensions",
"LoadStoreAction": {
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "MinMaxCoCAttachment",
"SizeSource": {
"Source": {
"Pass": "This",
"Attachment": "ColorAndCocInput"
},
"Multipliers": {
// 1/16 = 0.0625
"WidthMultiplier": 0.0625,
"HeightMultiplier": 0.0625
}
},
"ImageDescriptor": {
"Format": "R16G16_SNORM"
}
}
],
"Connections": [
{
"LocalSlot": "MinMaxCoC",
"AttachmentRef": {
"Pass": "This",
"Attachment": "MinMaxCoCAttachment"
}
}
],
"PassData": {
"$type": "ComputePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/NewDepthOfFieldTileReduce.shader"
},
"PipelineViewTag": "MainCamera"
}
}
}
}

@ -185,6 +185,34 @@
"Path": "Passes/DepthOfFieldWriteFocusDepthFromGpu.pass" "Path": "Passes/DepthOfFieldWriteFocusDepthFromGpu.pass"
}, },
{ {
"Name": "NewDepthOfFieldTemplate",
"Path": "Passes/NewDepthOfField.pass"
},
{
"Name": "NewDepthOfFieldDownsampleTemplate",
"Path": "Passes/NewDepthOfFieldDownsample.pass"
},
{
"Name": "NewDepthOfFieldTileReduceTemplate",
"Path": "Passes/NewDepthOfFieldTileReduce.pass"
},
{
"Name": "NewDepthOfFieldTile3x3Template",
"Path": "Passes/NewDepthOfFieldTile3x3.pass"
},
{
"Name": "NewDepthOfFieldFilterLargeTemplate",
"Path": "Passes/NewDepthOfFieldFilterLarge.pass"
},
{
"Name": "NewDepthOfFieldFilterSmallTemplate",
"Path": "Passes/NewDepthOfFieldFilterSmall.pass"
},
{
"Name": "NewDepthOfFieldCompositeTemplate",
"Path": "Passes/NewDepthOfFieldComposite.pass"
},
{
"Name": "EsmShadowmapsTemplate", "Name": "EsmShadowmapsTemplate",
"Path": "Passes/EsmShadowmaps.pass" "Path": "Passes/EsmShadowmaps.pass"
}, },

@ -112,20 +112,42 @@
} }
] ]
}, },
// Todo: remove the old depth of field implementation and rename NewDepthOfField -> DepthOfField
//{
// "Name": "DepthOfFieldPass",
// "TemplateName": "DepthOfFieldTemplate",
// "Enabled": true,
// "Connections": [
// {
// "LocalSlot": "DoFColorInput",
// "AttachmentRef": {
// "Pass": "TaaPass",
// "Attachment": "OutputColor"
// }
// },
// {
// "LocalSlot": "DoFDepthInput",
// "AttachmentRef": {
// "Pass": "Parent",
// "Attachment": "Depth"
// }
// }
// ]
//},
{ {
"Name": "DepthOfFieldPass", "Name": "DepthOfFieldPass",
"TemplateName": "DepthOfFieldTemplate", "TemplateName": "NewDepthOfFieldTemplate",
"Enabled": true, "Enabled": true,
"Connections": [ "Connections": [
{ {
"LocalSlot": "DoFColorInput", "LocalSlot": "LightingBuffer",
"AttachmentRef": { "AttachmentRef": {
"Pass": "TaaPass", "Pass": "TaaPass",
"Attachment": "OutputColor" "Attachment": "OutputColor"
} }
}, },
{ {
"LocalSlot": "DoFDepthInput", "LocalSlot": "Depth",
"AttachmentRef": { "AttachmentRef": {
"Pass": "Parent", "Pass": "Parent",
"Attachment": "Depth" "Attachment": "Depth"
@ -142,7 +164,7 @@
"LocalSlot": "InputOutput", "LocalSlot": "InputOutput",
"AttachmentRef": { "AttachmentRef": {
"Pass": "DepthOfFieldPass", "Pass": "DepthOfFieldPass",
"Attachment": "DoFOutput" "Attachment": "LightingBuffer"
} }
} }
] ]

@ -1,5 +1,5 @@
{ {
"Source" : "AuxGeomObject", "Source" : "AuxGeomObject.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source" : "AuxGeomObjectLit", "Source" : "AuxGeomObjectLit.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source" : "AuxGeomWorld", "Source" : "AuxGeomWorld.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source": "BRDFTextureCS", "Source": "BRDFTextureCS.azsl",
"ProgramSettings": "ProgramSettings":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "CheckerboardColorResolveCS", "Source": "CheckerboardColorResolveCS.azsl",
"CompilerHints": "CompilerHints":
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "LutGeneration", "Source" : "LutGeneration.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DepthPassSkin", "Source" : "DepthPassSkin.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source" : "DiffuseComposite", "Source" : "DiffuseComposite.azsl",
"RasterState" : "RasterState" :
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "DiffuseGlobalFullscreen", "Source" : "DiffuseGlobalFullscreen.azsl",
"RasterState" : "RasterState" :
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "DiffuseProbeGridDownsample", "Source" : "DiffuseProbeGridDownsample.azsl",
"RasterState" : "RasterState" :
{ {

@ -1,6 +1,6 @@
{ {
"Source" : "ImGui", "Source" : "ImGui.azsl",
"RasterState" : { "CullMode" : "None" }, "RasterState" : { "CullMode" : "None" },

@ -1,5 +1,5 @@
{ {
"Source": "LightCulling", "Source": "LightCulling.azsl",
"CompilerHints": "CompilerHints":
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "LightCullingHeatmap", "Source" : "LightCullingHeatmap.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "LightCullingRemap", "Source": "LightCullingRemap.azsl",
"Compiler": "Compiler":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "LightCullingTilePrepare", "Source": "LightCullingTilePrepare.azsl",
"CompilerHints": "CompilerHints":
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "RenderTexture", "Source" : "RenderTexture.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "MorphTargetCS", "Source": "MorphTargetCS.azsl",
"ProgramSettings": "ProgramSettings":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "CameraMotionVector", "Source": "CameraMotionVector.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "MeshMotionVector", "Source" : "MeshMotionVector.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source" : "MeshMotionVectorSkin", "Source" : "MeshMotionVectorSkin.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" }

@ -1,5 +1,5 @@
{ {
"Source" : "AcesOutputTransformLut", "Source" : "AcesOutputTransformLut.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "ApplyShaperLookupTable", "Source" : "ApplyShaperLookupTable.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "BakeAcesOutputTransformLutCS", "Source": "BakeAcesOutputTransformLutCS.azsl",
"ProgramSettings": "ProgramSettings":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "BlendColorGradingLuts", "Source": "BlendColorGradingLuts.azsl",
"DrawList" : "forward", "DrawList" : "forward",

@ -1,5 +1,5 @@
{ {
"Source": "BloomBlurCS", "Source": "BloomBlurCS.azsl",
"DrawList" : "forward", "DrawList" : "forward",

@ -1,5 +1,5 @@
{ {
"Source": "BloomCompositeCS", "Source": "BloomCompositeCS.azsl",
"DrawList" : "forward", "DrawList" : "forward",

@ -1,5 +1,5 @@
{ {
"Source": "BloomDownsampleCS", "Source": "BloomDownsampleCS.azsl",
"DrawList" : "forward", "DrawList" : "forward",

@ -1,5 +1,5 @@
{ {
"Source": "ContrastAdaptiveSharpening", "Source": "ContrastAdaptiveSharpening.azsl",
"ProgramSettings": { "ProgramSettings": {
"EntryPoints": [ "EntryPoints": [
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "ConvertToAcescg", "Source" : "ConvertToAcescg.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "DepthDownsample", "Source": "DepthDownsample.azsl",
"ProgramSettings" : "ProgramSettings" :
{ {

@ -14,6 +14,14 @@ inline float InvertDepth(float depth)
return 1.0f - depth; return 1.0f - depth;
} }
inline float4 InvertDepth(float4 depth)
{
// Convert depth from [1.0 - 0.0] to [0.0 - 1.0].
// Set the front(near side) to 0.0 and the back(far side) to 1.0.
return float4(1, 1, 1, 1) - depth;
}
inline float ConvertDofFactor(float depth, float far, float near, float focusDistance) inline float ConvertDofFactor(float depth, float far, float near, float focusDistance)
{ {
// dofFactor : The value Calculated from depth. // dofFactor : The value Calculated from depth.

@ -1,5 +1,5 @@
{ {
"Source" : "DepthOfFieldBlurBokeh", "Source" : "DepthOfFieldBlurBokeh.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DepthOfFieldComposite", "Source" : "DepthOfFieldComposite.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DepthOfFieldDownSample", "Source" : "DepthOfFieldDownSample.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DepthOfFieldMask", "Source" : "DepthOfFieldMask.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DepthOfFieldPrepare", "Source" : "DepthOfFieldPrepare.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "DepthOfFieldWriteFocusDepthFromGpu", "Source": "DepthOfFieldWriteFocusDepthFromGpu.azsl",
"ProgramSettings" : "ProgramSettings" :
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "DepthToLinearDepth", "Source" : "DepthToLinearDepth.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "DepthUpsample", "Source": "DepthUpsample.azsl",
"ProgramSettings" : "ProgramSettings" :
{ {

@ -1,5 +1,5 @@
{ {
"Source" : "DiffuseSpecularMerge", "Source" : "DiffuseSpecularMerge.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DisplayMapper", "Source" : "DisplayMapper.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source" : "DisplayMapperOnlyGammaCorrection", "Source" : "DisplayMapperOnlyGammaCorrection.azsl",
"DepthStencilState" : { "DepthStencilState" : {
"Depth" : { "Enable" : false } "Depth" : { "Enable" : false }

@ -1,5 +1,5 @@
{ {
"Source": "DownsampleLuminanceMinAvgMaxCS", "Source": "DownsampleLuminanceMinAvgMaxCS.azsl",
"ProgramSettings": "ProgramSettings":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "DownsampleMinAvgMaxCS", "Source": "DownsampleMinAvgMaxCS.azsl",
"ProgramSettings": "ProgramSettings":
{ {

@ -1,5 +1,5 @@
{ {
"Source": "EyeAdaptation", "Source": "EyeAdaptation.azsl",
"ProgramSettings" : "ProgramSettings" :

@ -1,5 +1,5 @@
{ {
"Source": "FastDepthAwareBlurHor", "Source": "FastDepthAwareBlurHor.azsl",
"ProgramSettings" : "ProgramSettings" :
{ {

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

Loading…
Cancel
Save