Initial phase of UI Canvas Editor rendering with Atom (#164)

* Move Draw2d.h to Include folder

* Initial phase of UI Canvas Editor rendering with Atom

* Simplify Draw2d by removing BeginDraw2d/EndDraw2d which is no longer needed

* Fix compile errors for non-unity builds
main
michabr 5 years ago committed by GitHub
parent 88d0853cfd
commit c66e2f4bcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,7 +11,7 @@
*/
#pragma once
#include <LyShine/ILyShine.h>
#include <IRenderer.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Color.h>
@ -115,355 +115,4 @@ public: // member functions
//! Implement virtual destructor just for safety.
virtual ~IDraw2d() {}
//! Start a section of 2D drawing function calls. This will set appropriate render state.
//
//! \param deferCalls If true then actual render calls are deferred until the end of the frame
virtual void BeginDraw2d(bool deferCalls = false) = 0;
//! Start a section of 2D drawing function calls. This will set appropriate render state.
//! This variant allows the viewport size to be specified
//
//! \param viewportSize The size of the viewport being rendered to
//! \param deferCalls If true then actual render calls are deferred until the end of the frame
virtual void BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls = false) = 0;
//! End a section of 2D drawing function calls. This will reset some render state.
virtual void EndDraw2d() = 0;
//! Draw a textured quad with the top left corner at the given position.
//
//! The image is drawn with the color specified by SetShapeColor and the opacity
//! passed as an argument.
//! If rotation is non-zero then the quad is rotated. If the pivot point is
//! provided then the points of the quad are rotated about that point, otherwise
//! they are rotated about the top left corner of the quad.
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param position Position of the top left corner of the quad (before rotation) in pixels
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
//! \param opacity The alpha value used when blending
//! \param rotation Angle of rotation in degrees counter-clockwise
//! \param pivotPoint The point about which the quad is rotated
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
//! point of the quad and the second is the UV coord of the bottom right point of the quad
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
virtual void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr) = 0;
//! Draw a textured quad where the position specifies the point specified by the alignment.
//
//! Rotation is always around the position.
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param position Position align point of the quad (before rotation) in pixels
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
//! \param horizontalAlignment Specifies how the quad is horizontally aligned to the given position
//! \param verticalAlignment Specifies how the quad is vertically aligned to the given position
//! \param opacity The alpha value used when blending
//! \param rotation Angle of rotation in degrees counter-clockwise
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
//! point of the quad and the second is the UV coord of the bottom right point of the quad
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
virtual void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
HAlign horizontalAlignment, VAlign verticalAlignment,
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr) = 0;
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
//
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param verts An array of 4 vertices, in clockwise order (e.g. top left, top right, bottom right, bottom left)
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawQuad(int texId, VertexPosColUV* verts,
int blendMode = UseDefault,
Rounding pixelRounding = Rounding::Nearest,
int baseState = UseDefault) = 0;
//! Draw a line
//
//! \param start The start position
//! \param end The end position
//! \param color The color of the line
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color,
int blendMode = UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = UseDefault) = 0;
//! Draw a line with a texture so it can be dotted or dashed
//
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param verts An array of 2 vertices for the start and end points of the line
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawLineTextured(int texId, VertexPosColUV* verts,
int blendMode = UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = UseDefault) = 0;
//! Draw a text string. Only supports ASCII text.
//
//! The font and effect used to render the text are specified in the textOptions structure
//! \param textString A null terminated ASCII text string. May contain \n characters
//! \param position Position of the text in pixels. Alignment values in textOptions affect actual position
//! \param pointSize The size of the font to use
//! \param opacity The opacity (alpha value) to use to draw the text
//! \param textOptions Pointer to an options struct. If null the default options are used
virtual void DrawText(const char* textString, AZ::Vector2 position, float pointSize,
float opacity = 1.0f, TextOptions* textOptions = nullptr) = 0;
//! Get the width and height (in pixels) that would be used to draw the given text string.
//
//! Pass the same parameter values that would be used to draw the string
virtual AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr) = 0;
//! Get the width of the rendering viewport (in pixels).
//
//! If rendering full screen this is the native width from IRenderer
virtual float GetViewportWidth() const = 0;
//! Get the height of the rendering viewport (in pixels).
//
//! If rendering full screen this is the native width from IRenderer
virtual float GetViewportHeight() const = 0;
//! Get the default values that would be used if no image options were passed in
//
//! This is a convenient way to initialize the imageOptions struct
virtual const ImageOptions& GetDefaultImageOptions() const = 0;
//! Get the default values that would be used if no text options were passed in
//
//! This is a convenient way to initialize the textOptions struct
virtual const TextOptions& GetDefaultTextOptions() const = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Helper class for using the IDraw2d interface
//!
//! The Draw2dHelper class is an inline wrapper that provides two convenience features:
//! 1. It automatically calls BeginDraw2d/EndDraw2d in its construction/destruction.
//! 2. It automatically sets member options structures to their defaults and provides set functions
//! to set them.
class Draw2dHelper
{
public: // member functions
//! Start a section of 2D drawing function calls. This will set appropriate render state.
Draw2dHelper(bool deferCalls = false)
: m_draw2d(GetDraw2d())
{
if (m_draw2d)
{
m_draw2d->BeginDraw2d(deferCalls);
m_imageOptions = m_draw2d->GetDefaultImageOptions();
m_textOptions = m_draw2d->GetDefaultTextOptions();
}
}
//! End a section of 2D drawing function calls. This will reset some render state.
~Draw2dHelper()
{
if (m_draw2d)
{
m_draw2d->EndDraw2d();
}
}
//! Draw a textured quad, optional rotation is counter-clockwise in degrees.
//
//! See IDraw2d:DrawImage for parameter descriptions
void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr)
{
if (m_draw2d)
{
m_draw2d->DrawImage(texId, position, size, opacity, rotation, pivotPoint, minMaxTexCoords, &m_imageOptions);
}
}
//! Draw a textured quad where the position specifies the point specified by the alignment.
//
//! See IDraw2d:DrawImageAligned for parameter descriptions
void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment,
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr)
{
if (m_draw2d)
{
m_draw2d->DrawImageAligned(texId, position, size, horizontalAlignment, verticalAlignment,
opacity, rotation, minMaxTexCoords, &m_imageOptions);
}
}
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
//
//! See IDraw2d:DrawQuad for parameter descriptions
void DrawQuad(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawQuad(texId, verts, blendMode, pixelRounding, baseState);
}
}
//! Draw a line
//
//! See IDraw2d:DrawLine for parameter descriptions
void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawLine(start, end, color, blendMode, pixelRounding, baseState);
}
}
//! Draw a line with a texture so it can be dotted or dashed
//
//! See IDraw2d:DrawLineTextured for parameter descriptions
void DrawLineTextured(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawLineTextured(texId, verts, blendMode, pixelRounding, baseState);
}
}
//! Draw a text string. Only supports ASCII text.
//
//! See IDraw2d:DrawText for parameter descriptions
void DrawText(const char* textString, AZ::Vector2 position, float pointSize, float opacity = 1.0f)
{
if (m_draw2d)
{
m_draw2d->DrawText(textString, position, pointSize, opacity, &m_textOptions);
}
}
//! Get the width and height (in pixels) that would be used to draw the given text string.
//
//! See IDraw2d:GetTextSize for parameter descriptions
AZ::Vector2 GetTextSize(const char* textString, float pointSize)
{
if (m_draw2d)
{
return m_draw2d->GetTextSize(textString, pointSize, &m_textOptions);
}
else
{
return AZ::Vector2(0, 0);
}
}
// State management
//! Set the blend mode used for images, default is GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA.
void SetImageBlendMode(int mode) { m_imageOptions.blendMode = mode; }
//! Set the color used for DrawImage and other image drawing.
void SetImageColor(AZ::Vector3 color) { m_imageOptions.color = color; }
//! Set whether images are rounded to have the points on exact pixel boundaries.
void SetImagePixelRounding(IDraw2d::Rounding round) { m_imageOptions.pixelRounding = round; }
//! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST.
void SetImageBaseState(int state) { m_imageOptions.baseState = state; }
//! Set the text font.
void SetTextFont(IFFont* font) { m_textOptions.font = font; }
//! Set the text font effect index.
void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; }
//! Set the text color.
void SetTextColor(AZ::Vector3 color) { m_textOptions.color = color; }
//! Set the text alignment.
void SetTextAlignment(IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment)
{
m_textOptions.horizontalAlignment = horizontalAlignment;
m_textOptions.verticalAlignment = verticalAlignment;
}
//! Set a drop shadow for text drawing. An alpha of zero disables drop shadow.
void SetTextDropShadow(AZ::Vector2 offset, AZ::Color color)
{
m_textOptions.dropShadowOffset = offset;
m_textOptions.dropShadowColor = color;
}
//! Set a rotation for the text. The text rotates around its position (taking into account alignment).
void SetTextRotation(float rotation)
{
m_textOptions.rotation = rotation;
}
//! Set the base state (that blend mode etc is combined with) used for text, default is GS_NODEPTHTEST.
void SetTextBaseState(int state) { m_textOptions.baseState = state; }
public: // static member functions
//! Helper to get the IDraw2d interface
static IDraw2d* GetDraw2d() { return (gEnv && gEnv->pLyShine) ? gEnv->pLyShine->GetDraw2d() : nullptr; }
//! Get the width of the rendering viewport (in pixels).
static float GetViewportWidth()
{
IDraw2d* draw2d = GetDraw2d();
return (draw2d) ? draw2d->GetViewportWidth() : 0.0f;
}
//! Get the height of the rendering viewport (in pixels).
static float GetViewportHeight()
{
IDraw2d* draw2d = GetDraw2d();
return (draw2d) ? draw2d->GetViewportHeight() : 0.0f;
}
//! Round the X and Y coordinates of a point using the given rounding policy
template<typename T>
static T RoundXY(T value, IDraw2d::Rounding roundingType)
{
T result = value;
switch (roundingType)
{
case IDraw2d::Rounding::None:
// nothing to do
break;
case IDraw2d::Rounding::Nearest:
result.SetX(floor(value.GetX() + 0.5f));
result.SetY(floor(value.GetY() + 0.5f));
break;
case IDraw2d::Rounding::Down:
result.SetX(floor(value.GetX()));
result.SetY(floor(value.GetY()));
break;
case IDraw2d::Rounding::Up:
result.SetX(ceil(value.GetX()));
result.SetY(ceil(value.GetY()));
break;
}
return result;
}
protected: // attributes
IDraw2d::ImageOptions m_imageOptions; //!< image options are stored locally and updated by member functions
IDraw2d::TextOptions m_textOptions; //!< text options are stored locally and updated by member functions
IDraw2d* m_draw2d;
};

@ -1,79 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <LyShine/IDraw2d.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Interface used by UI components to render to the canvas
//
//! The IUiRenderer provides helper functions for UI rendering and also manages state that
//! persists between UI elements when rendering a UI canvas.
//! For example one UI component can turn on stencil test and that affects all UI rendering
//! until it is turned off.
//!
//! This is a singleton class that is accessed via IUiRenderer::Get() which is a shortcut for
//! gEnv->pLyShine()->GetUiRenderer();
class IUiRenderer
{
public: // types
public: // member functions
//! Implement virtual destructor for safety.
virtual ~IUiRenderer() {}
//! Start the rendering of a UI canvas
virtual void BeginCanvasRender(AZ::Vector2 viewportSize) = 0;
//! End the rendering of a UI canvas
virtual void EndCanvasRender() = 0;
//! Get the current base state
virtual int GetBaseState() = 0;
//! Set the base state
virtual void SetBaseState(int state) = 0;
//! Get the current stencil test reference value
virtual uint32 GetStencilRef() = 0;
//! Set the stencil test reference value
virtual void SetStencilRef(uint32) = 0;
//! Increment the current stencil reference value
virtual void IncrementStencilRef() = 0;
//! Decrement the current stencil reference value
virtual void DecrementStencilRef() = 0;
//! Get flag that indicates we are rendering into a mask. Used to avoid masks on child mask elements.
virtual bool IsRenderingToMask() = 0;
//! Set flag that we are rendering into a mask. Used to avoid masks on child mask elements.
virtual void SetIsRenderingToMask(bool isRenderingToMask) = 0;
//! Push an alpha fade, this is multiplied with any existing alpha fade from parents
virtual void PushAlphaFade(float alphaFadeValue) = 0;
//! Pop an alpha fade off the stack
virtual void PopAlphaFade() = 0;
//! Get the current alpha fade value
virtual float GetAlphaFade() const = 0;
public: // static member functions
//! Helper function to get the singleton UiRenderer
static IUiRenderer* Get() { return gEnv->pLyShine->GetUiRenderer(); }
};

@ -20,6 +20,7 @@
#include <AzCore/Component/Entity.h>
#include <LyShine/UiAssetTypes.h>
#include <LyShine/UiBase.h>
////////////////////////////////////////////////////////////////////////////////////////////////////

@ -12,7 +12,7 @@
#pragma once
#include <AzCore/Math/Vector2.h>
#include <LyShine/IDraw2d.h>
#include <LyShine/Draw2d.h>
//! Abstract base class for drag interactions in the UI Editor viewport window.
class ViewportDragInteraction

@ -11,6 +11,8 @@
*/
#pragma once
#include <LyShine/Draw2d.h>
namespace ViewportHelpers
{
//-------------------------------------------------------------------------------

@ -12,25 +12,34 @@
#include "UiCanvasEditor_precompiled.h"
#include "EditorCommon.h"
#include <LyShine/Draw2d.h>
#include <Atom/RPI.Public/Image/StreamingImage.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
ViewportIcon::ViewportIcon(const char* textureFilename)
: m_texture(gEnv->pRenderer->EF_LoadTexture(textureFilename, FT_DONT_STREAM))
{
m_image = CDraw2d::LoadTexture(textureFilename);
}
ViewportIcon::~ViewportIcon()
{
gEnv->pRenderer->RemoveTexture(m_texture->GetTextureID());
}
AZ::Vector2 ViewportIcon::GetTextureSize() const
{
return AZ::Vector2(aznumeric_cast<float>(m_texture->GetWidth()), aznumeric_cast<float>(m_texture->GetHeight()));
if (m_image)
{
AZ::RHI::Size size = m_image->GetDescriptor().m_size;
return AZ::Vector2(size.m_width, size.m_height);
}
return AZ::Vector2(0.0f, 0.0f);
}
void ViewportIcon::DrawImageAligned(Draw2dHelper& draw2d, AZ::Vector2& pivot, float opacity)
{
draw2d.DrawImageAligned(m_texture->GetTextureID(),
draw2d.DrawImageAligned(m_image,
pivot,
GetTextureSize(),
IDraw2d::HAlign::Center,
@ -43,7 +52,7 @@ void ViewportIcon::DrawImageTiled(Draw2dHelper& draw2d, IDraw2d::VertexPosColUV*
// Use default blending and rounding modes
int blendMode = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
IDraw2d::Rounding rounding = IDraw2d::Rounding::Nearest;
draw2d.DrawQuad(m_texture->GetTextureID(), verts, blendMode, rounding);
draw2d.DrawQuad(m_image, verts, blendMode, rounding);
}
void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 bound0, AZ::Vector2 bound1)
@ -73,7 +82,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2
verts[0].uv = AZ::Vector2(0.0f, 0.5f);
verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f);
draw2d.DrawLineTextured(m_texture->GetTextureID(), verts);
draw2d.DrawLineTextured(m_image, verts);
}
// bound0
@ -89,7 +98,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2
verts[0].uv = AZ::Vector2(0.0f, 0.5f);
verts[1].uv = AZ::Vector2(endTexCoordV, 0.5f);
draw2d.DrawLineTextured(m_texture->GetTextureID(), verts);
draw2d.DrawLineTextured(m_image, verts);
}
// bound0
@ -105,7 +114,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2
verts[0].uv = AZ::Vector2(0.0f, 0.5f);
verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f);
draw2d.DrawLineTextured(m_texture->GetTextureID(), verts);
draw2d.DrawLineTextured(m_image, verts);
}
// bound0
@ -121,7 +130,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2
verts[0].uv = AZ::Vector2(0.0f, 0.5f);
verts[1].uv = AZ::Vector2(endTexCoordV, 0.5f);
draw2d.DrawLineTextured(m_texture->GetTextureID(), verts);
draw2d.DrawLineTextured(m_image, verts);
}
}
@ -189,7 +198,7 @@ void ViewportIcon::Draw(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, const AZ::M
verts[3].position = originPos - widthVec * originRatio.GetX() + heightVec * (1.0f - originRatio.GetY());
}
draw2d.DrawQuad(m_texture->GetTextureID(), verts);
draw2d.DrawQuad(m_image, verts);
}
void ViewportIcon::DrawAnchorLines(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, AZ::Vector2 targetPos, const AZ::Matrix4x4& transform,
@ -252,7 +261,7 @@ void ViewportIcon::DrawDistanceLine(Draw2dHelper& draw2d, AZ::Vector2 start, AZ:
verts[1].color = dottedColor;
verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f);
draw2d.DrawLineTextured(m_texture->GetTextureID(), verts);
draw2d.DrawLineTextured(m_image, verts);
// Now draw the text rotated to match the angle of the line and slightly offset from the center point
@ -379,7 +388,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d,
float rectHeight = heightVec.GetLength();
// the outline "width" will be based on the texture height
int textureHeight = m_texture->GetHeight();
float textureHeight = GetTextureSize().GetY();
if (textureHeight <= 0)
{
return; // should never happen - avoiding possible divide by zero later
@ -464,6 +473,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d,
5, 1, 7, 1, 7, 3, // right quad
};
#ifdef LYSHINE_ATOM_TODO
IRenderer* renderer = gEnv->pRenderer;
renderer->SetTexture(m_texture->GetTextureID());
@ -472,4 +482,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d,
// This will end up using DrawIndexedPrimitive to render the quad
renderer->DrawDynVB(vertices, indicies, NUM_VERTS, NUM_INDICES, prtTriangleList);
#else
// LYSHINE_ATOM_TODO - add option in Draw2d to draw indexed primitive for this textured element outline
#endif
}

@ -11,6 +11,8 @@
*/
#pragma once
#include <Atom/RPI.Reflect/Image/Image.h>
class ViewportIcon
{
public:
@ -48,6 +50,5 @@ public:
void DrawElementRectOutline(Draw2dHelper& draw2d, AZ::EntityId entityId, AZ::Color color);
private:
ITexture* m_texture;
AZ::Data::Instance<AZ::RPI::Image> m_image;
};

@ -21,6 +21,7 @@
#include <QViewportSettings.h>
#include <LyShine/Bus/UiEditorCanvasBus.h>
#include <LyShine/Draw2d.h>
#include "LyShine.h"
#include "UiRenderer.h"
@ -277,6 +278,8 @@ void ViewportWidget::InitUiRenderer()
// Only one viewport/renderer is currently supported in the UI Editor
CLyShine* lyShine = static_cast<CLyShine*>(gEnv->pLyShine);
lyShine->SetUiRendererForEditor(m_uiRenderer);
m_draw2d = AZStd::make_shared<CDraw2d>(GetViewportContext());
}
ViewportInteraction* ViewportWidget::GetViewportInteraction()
@ -914,7 +917,7 @@ void ViewportWidget::RenderEditMode(float deltaTime)
return; // this can happen if a render happens during a restart
}
Draw2dHelper draw2d; // sets and resets 2D draw mode in constructor/destructor
Draw2dHelper draw2d(m_draw2d.get()); // sets and resets 2D draw mode in constructor/destructor
QTreeWidgetItemRawPtrQList selection = m_editorWindow->GetHierarchy()->selectedItems();
@ -1142,7 +1145,7 @@ void ViewportWidget::RenderPreviewMode(float deltaTime)
AZ::Vector2 topLeftInViewportSpace = CanvasHelpers::GetViewportPoint(canvasEntityId, AZ::Vector2(0.0f, 0.0f));
AZ::Vector2 bottomRightInViewportSpace = CanvasHelpers::GetViewportPoint(canvasEntityId, canvasSize);
AZ::Vector2 sizeInViewportSpace = bottomRightInViewportSpace - topLeftInViewportSpace;
Draw2dHelper draw2d;
Draw2dHelper draw2d(m_draw2d.get())
int texId = gEnv->pRenderer->GetBlackTextureId();
draw2d.DrawImage(texId, topLeftInViewportSpace, sizeInViewportSpace);
#endif

@ -25,6 +25,7 @@
class RulerWidget;
class QMimeData;
class UiRenderer;
class CDraw2d;
class ViewportWidget
: public AtomToolsFramework::RenderViewportWidget
@ -201,4 +202,5 @@ private: // data
bool m_fontTextureHasChanged = false;
AZStd::shared_ptr<UiRenderer> m_uiRenderer;
AZStd::shared_ptr<CDraw2d> m_draw2d;
};

@ -0,0 +1,517 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <LyShine/IDraw2d.h>
#include <LyShine/ILyShine.h>
#include <Atom/Bootstrap/BootstrapNotificationBus.h>
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
#include <Atom/RPI.Reflect/Image/Image.h>
#include <Atom/RPI.Public/ViewportContext.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Implementation of IDraw2d interface for 2D drawing in screen space
//
//! The CDraw2d class implements the IDraw2d interface for drawing 2D images, shapes and text.
//! Positions and sizes are specified in pixels in the associated 2D viewport.
class CDraw2d
: public IDraw2d // LYSHINE_ATOM_TODO - keep around until gEnv->pLyShine is replaced by bus interface
, public AZ::Render::Bootstrap::NotificationBus::Handler
{
public: // member functions
//! Constructor, constructed by the LyShine class
CDraw2d(AZ::RPI::ViewportContextPtr viewportContext = nullptr);
// IDraw2d
~CDraw2d() override;
// ~IDraw2d
//! Draw a textured quad with the top left corner at the given position.
//
//! The image is drawn with the color specified by SetShapeColor and the opacity
//! passed as an argument.
//! If rotation is non-zero then the quad is rotated. If the pivot point is
//! provided then the points of the quad are rotated about that point, otherwise
//! they are rotated about the top left corner of the quad.
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param position Position of the top left corner of the quad (before rotation) in pixels
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
//! \param opacity The alpha value used when blending
//! \param rotation Angle of rotation in degrees counter-clockwise
//! \param pivotPoint The point about which the quad is rotated
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
//! point of the quad and the second is the UV coord of the bottom right point of the quad
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
void DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr);
//! Draw a textured quad where the position specifies the point specified by the alignment.
//
//! Rotation is always around the position.
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param position Position align point of the quad (before rotation) in pixels
//! \param size The width and height of the quad. Use texture width and height to avoid minification,
//! magnification or stretching (assuming the minMaxTexCoords are left to the default)
//! \param horizontalAlignment Specifies how the quad is horizontally aligned to the given position
//! \param verticalAlignment Specifies how the quad is vertically aligned to the given position
//! \param opacity The alpha value used when blending
//! \param rotation Angle of rotation in degrees counter-clockwise
//! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left
//! point of the quad and the second is the UV coord of the bottom right point of the quad
//! \param imageOptions Optional struct specifying options that tend to be the same from call to call
void DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size,
HAlign horizontalAlignment, VAlign verticalAlignment,
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr);
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
//
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param verts An array of 4 vertices, in clockwise order (e.g. top left, top right, bottom right, bottom left)
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image,
VertexPosColUV* verts,
int blendMode = UseDefault,
Rounding pixelRounding = Rounding::Nearest,
int baseState = UseDefault);
//! Draw a line
//
//! \param start The start position
//! \param end The end position
//! \param color The color of the line
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color,
int blendMode = UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = UseDefault);
//! Draw a line with a texture so it can be dotted or dashed
//
//! \param texId The texture ID returned by ITexture::GetTextureID()
//! \param verts An array of 2 vertices for the start and end points of the line
//! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA)
//! \param pixelRounding Whether and how to round pixel coordinates
//! \param baseState Additional render state to pass to or into value passed to renderer SetState
virtual void DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image,
VertexPosColUV* verts,
int blendMode = UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = UseDefault);
//! Draw a text string. Only supports ASCII text.
//
//! The font and effect used to render the text are specified in the textOptions structure
//! \param textString A null terminated ASCII text string. May contain \n characters
//! \param position Position of the text in pixels. Alignment values in textOptions affect actual position
//! \param pointSize The size of the font to use
//! \param opacity The opacity (alpha value) to use to draw the text
//! \param textOptions Pointer to an options struct. If null the default options are used
void DrawText(const char* textString, AZ::Vector2 position, float pointSize,
float opacity = 1.0f, TextOptions* textOptions = nullptr);
//! Get the width and height (in pixels) that would be used to draw the given text string.
//
//! Pass the same parameter values that would be used to draw the string
AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr);
//! Get the width of the rendering viewport (in pixels).
float GetViewportWidth() const;
//! Get the height of the rendering viewport (in pixels).
float GetViewportHeight() const;
//! Get the default values that would be used if no image options were passed in
//
//! This is a convenient way to initialize the imageOptions struct
virtual const ImageOptions& GetDefaultImageOptions() const;
//! Get the default values that would be used if no text options were passed in
//
//! This is a convenient way to initialize the textOptions struct
virtual const TextOptions& GetDefaultTextOptions() const;
//! Render the primitives that have been deferred
void RenderDeferredPrimitives();
//! Specify whether to defer future primitives or render them right away
void SetDeferPrimitives(bool deferPrimitives);
//! Return whether future primitives will be deferred or rendered right away
bool GetDeferPrimitives();
private:
AZ_DISABLE_COPY_MOVE(CDraw2d);
// AZ::Render::Bootstrap::NotificationBus overrides
void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override;
public: // static member functions
//! Given a position and size and an alignment return the top left corner of the aligned quad
static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment);
//! Helper to load a texture
static AZ::Data::Instance<AZ::RPI::Image> LoadTexture(const AZStd::string& pathName);
protected: // types and constants
enum
{
MAX_VERTICES_IN_PRIM = 6
};
// Cached shader data
struct Draw2dShaderData
{
AZ::RHI::ShaderInputImageIndex m_imageInputIndex;
AZ::RHI::ShaderInputConstantIndex m_viewProjInputIndex;
};
class DeferredPrimitive
{
public:
virtual ~DeferredPrimitive() {};
virtual void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const = 0;
};
class DeferredQuad
: public DeferredPrimitive
{
public:
~DeferredQuad() override {};
void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const override;
AZ::Vector2 m_points[4];
AZ::Vector2 m_texCoords[4];
uint32 m_packedColors[4];
AZ::Data::Instance<AZ::RPI::Image> m_image;
int m_state;
};
class DeferredLine
: public DeferredPrimitive
{
public:
~DeferredLine() override {};
void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const override;
AZ::Data::Instance<AZ::RPI::Image> m_image;
AZ::Vector2 m_points[2];
AZ::Vector2 m_texCoords[2];
uint32 m_packedColors[2];
int m_state;
};
class DeferredText
: public DeferredPrimitive
{
public:
~DeferredText() override {};
void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const override;
STextDrawContext m_fontContext;
IFFont* m_font;
AZ::Vector2 m_position;
std::string m_string;
};
protected: // member functions
//! Rotate an array of points around the z-axis at the pivot point.
//
//! Angle is in degrees counter-clockwise
void RotatePointsAboutPivot(AZ::Vector2* points, int numPoints, AZ::Vector2 pivot, float angle) const;
//! Helper function to render a text string
void DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex,
AZ::Vector2 position, float pointSize, AZ::Color color, float rotation,
HAlign horizontalAlignment, VAlign verticalAlignment, int baseState);
//! Draw or defer a quad
void DrawOrDeferQuad(const DeferredQuad* quad);
//! Draw or defer a line
void DrawOrDeferLine(const DeferredLine* line);
//! Get specified viewport context or default viewport context if not specified
AZ::RPI::ViewportContextPtr GetViewportContext() const;
protected: // attributes
ImageOptions m_defaultImageOptions; //!< The default image options used if nullptr is passed
TextOptions m_defaultTextOptions; //!< The default text options used if nullptr is passed
//! True if the actual render of the primitives should be deferred to a RenderDeferredPrimitives call
bool m_deferCalls;
std::vector<DeferredPrimitive*> m_deferredPrimitives;
AZ::RPI::ViewportContextPtr m_viewportContext;
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> m_dynamicDraw;
Draw2dShaderData m_shaderData;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Helper class for using the IDraw2d interface
//!
//! The Draw2dHelper class is an inline wrapper that provides the convenience feature of
//! automatically setting member options structures to their defaults and providing set functions.
class Draw2dHelper
{
public: // member functions
//! Start a section of 2D drawing function calls that will render to the default viewport
Draw2dHelper(bool deferCalls = false)
{
InitCommon(nullptr, deferCalls);
}
//! Start a section of 2D drawing function calls that will render to the viewport
//! associated with the specified Draw2d object
Draw2dHelper(CDraw2d* draw2d, bool deferCalls = false)
{
InitCommon(draw2d, deferCalls);
}
void InitCommon(CDraw2d* draw2d, bool deferCalls)
{
m_draw2d = draw2d;
if (!m_draw2d)
{
// Set to default which is the game's draw 2d object
m_draw2d = GetDefaultDraw2d();
}
if (m_draw2d)
{
m_previousDeferCalls = m_draw2d->GetDeferPrimitives();
m_draw2d->SetDeferPrimitives(deferCalls);
m_imageOptions = m_draw2d->GetDefaultImageOptions();
m_textOptions = m_draw2d->GetDefaultTextOptions();
}
}
//! End a section of 2D drawing function calls.
~Draw2dHelper()
{
if (m_draw2d)
{
m_draw2d->SetDeferPrimitives(m_previousDeferCalls);
}
}
//! Draw a textured quad, optional rotation is counter-clockwise in degrees.
//
//! See IDraw2d:DrawImage for parameter descriptions
void DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr)
{
if (m_draw2d)
{
m_draw2d->DrawImage(image, position, size, opacity, rotation, pivotPoint, minMaxTexCoords, &m_imageOptions);
}
}
//! Draw a textured quad where the position specifies the point specified by the alignment.
//
//! See IDraw2d:DrawImageAligned for parameter descriptions
void DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size,
IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment,
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr)
{
if (m_draw2d)
{
m_draw2d->DrawImageAligned(image, position, size, horizontalAlignment, verticalAlignment,
opacity, rotation, minMaxTexCoords, &m_imageOptions);
}
}
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
//
//! See IDraw2d:DrawQuad for parameter descriptions
void DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawQuad(image, verts, blendMode, pixelRounding, baseState);
}
}
//! Draw a line
//
//! See IDraw2d:DrawLine for parameter descriptions
void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawLine(start, end, color, blendMode, pixelRounding, baseState);
}
}
//! Draw a line with a texture so it can be dotted or dashed
//
//! See IDraw2d:DrawLineTextured for parameter descriptions
void DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault,
IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest,
int baseState = IDraw2d::UseDefault)
{
if (m_draw2d)
{
m_draw2d->DrawLineTextured(image, verts, blendMode, pixelRounding, baseState);
}
}
//! Draw a text string. Only supports ASCII text.
//
//! See IDraw2d:DrawText for parameter descriptions
void DrawText(const char* textString, AZ::Vector2 position, float pointSize, float opacity = 1.0f)
{
if (m_draw2d)
{
m_draw2d->DrawText(textString, position, pointSize, opacity, &m_textOptions);
}
}
//! Get the width and height (in pixels) that would be used to draw the given text string.
//
//! See IDraw2d:GetTextSize for parameter descriptions
AZ::Vector2 GetTextSize(const char* textString, float pointSize)
{
if (m_draw2d)
{
return m_draw2d->GetTextSize(textString, pointSize, &m_textOptions);
}
else
{
return AZ::Vector2(0, 0);
}
}
// State management
//! Set the blend mode used for images, default is GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA.
void SetImageBlendMode(int mode) { m_imageOptions.blendMode = mode; }
//! Set the color used for DrawImage and other image drawing.
void SetImageColor(AZ::Vector3 color) { m_imageOptions.color = color; }
//! Set whether images are rounded to have the points on exact pixel boundaries.
void SetImagePixelRounding(IDraw2d::Rounding round) { m_imageOptions.pixelRounding = round; }
//! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST.
void SetImageBaseState(int state) { m_imageOptions.baseState = state; }
//! Set the text font.
void SetTextFont(IFFont* font) { m_textOptions.font = font; }
//! Set the text font effect index.
void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; }
//! Set the text color.
void SetTextColor(AZ::Vector3 color) { m_textOptions.color = color; }
//! Set the text alignment.
void SetTextAlignment(IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment)
{
m_textOptions.horizontalAlignment = horizontalAlignment;
m_textOptions.verticalAlignment = verticalAlignment;
}
//! Set a drop shadow for text drawing. An alpha of zero disables drop shadow.
void SetTextDropShadow(AZ::Vector2 offset, AZ::Color color)
{
m_textOptions.dropShadowOffset = offset;
m_textOptions.dropShadowColor = color;
}
//! Set a rotation for the text. The text rotates around its position (taking into account alignment).
void SetTextRotation(float rotation)
{
m_textOptions.rotation = rotation;
}
//! Set the base state (that blend mode etc is combined with) used for text, default is GS_NODEPTHTEST.
void SetTextBaseState(int state) { m_textOptions.baseState = state; }
public: // static member functions
//! Helper to get the default IDraw2d interface
static CDraw2d* GetDefaultDraw2d()
{
if (gEnv && gEnv->pLyShine) // LYSHINE_ATOM_TODO - remove pLyShine and use bus interface
{
IDraw2d* draw2d = gEnv->pLyShine->GetDraw2d();
return reinterpret_cast<CDraw2d*>(draw2d);
}
return nullptr;
}
//! Round the X and Y coordinates of a point using the given rounding policy
template<typename T>
static T RoundXY(T value, IDraw2d::Rounding roundingType)
{
T result = value;
switch (roundingType)
{
case IDraw2d::Rounding::None:
// nothing to do
break;
case IDraw2d::Rounding::Nearest:
result.SetX(floor(value.GetX() + 0.5f));
result.SetY(floor(value.GetY() + 0.5f));
break;
case IDraw2d::Rounding::Down:
result.SetX(floor(value.GetX()));
result.SetY(floor(value.GetY()));
break;
case IDraw2d::Rounding::Up:
result.SetX(ceil(value.GetX()));
result.SetY(ceil(value.GetY()));
break;
}
return result;
}
protected: // attributes
IDraw2d::ImageOptions m_imageOptions; //!< image options are stored locally and updated by member functions
IDraw2d::TextOptions m_textOptions; //!< text options are stored locally and updated by member functions
CDraw2d* m_draw2d;
bool m_previousDeferCalls;
};

@ -10,17 +10,24 @@
*
*/
#include "LyShine_precompiled.h"
#include "Draw2d.h"
#include "IFont.h"
#include "IRenderer.h"
#include <LyShine/Draw2d.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/MatrixUtils.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Public/Image/StreamingImage.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
static const int g_defaultBlendState = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
static const int g_defaultBaseState = GS_NODEPTHTEST;
static const int g_2dModeNotStarted = -1;
////////////////////////////////////////////////////////////////////////////////////////////////////
// LOCAL STATIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -37,9 +44,9 @@ static AZ::u32 PackARGB8888(const AZ::Color& color)
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
CDraw2d::CDraw2d()
CDraw2d::CDraw2d(AZ::RPI::ViewportContextPtr viewportContext)
: m_deferCalls(false)
, m_nestLevelAtWhichStarted2dMode(g_2dModeNotStarted)
, m_viewportContext(viewportContext)
{
// These default options are set here and never change. They are stored so that if a null options
// structure is passed into the draw functions then this default one can be used instead
@ -57,78 +64,75 @@ CDraw2d::CDraw2d()
m_defaultTextOptions.dropShadowColor.Set(0.0f, 0.0f, 0.0f, 0.0f);
m_defaultTextOptions.rotation = 0.0f;
m_defaultTextOptions.baseState = g_defaultBaseState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
CDraw2d::~CDraw2d()
{
AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::BeginDraw2d(bool deferCalls)
CDraw2d::~CDraw2d()
{
IRenderer* renderer = gEnv->pRenderer;
AZ::Vector2 viewportSize(
static_cast<float>(renderer->GetOverlayWidth()),
static_cast<float>(renderer->GetOverlayHeight()));
BeginDraw2d(viewportSize, deferCalls);
AZ::Render::Bootstrap::NotificationBus::Handler::BusDisconnect();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls)
void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene)
{
// So that nested calls to BeginDraw2d/EndDraw2d do not end 2D drawmode prematurely we only
// switch to 2D mode once and do not do it again until the corresponding call to EndDraw2d
// is processed.
// It may seem overkill to allow nested calls rather than just asserting in that case. But
// a) it is more flexible to do so
// b) it can be useful to draw some debug primitives in deferred mode while rendering a
// canvas in non-deferred mode for example
// Push the current state of the m_deferCalls onto a stack to support nested calls
m_deferCallsFlagStack.push(m_deferCalls);
// At this point the RPI is ready for use
m_deferCalls = deferCalls;
// Load the shader to be used for 2d drawing
const char* shaderFilepath = "Shaders/SimpleTextured.azshader";
AZ::Data::Instance<AZ::RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath);
// if this is the outermost call with non-deferred rendering then switch to 2D mode
if (!m_deferCalls && m_nestLevelAtWhichStarted2dMode == g_2dModeNotStarted)
// Set scene to be associated with the dynamic draw context
AZ::RPI::ScenePtr scene;
if (m_viewportContext)
{
IRenderer* renderer = gEnv->pRenderer;
renderer->SetCullMode(R_CULL_DISABLE);
renderer->Set2DMode(static_cast<uint32>(viewportSize.GetX()), static_cast<uint32>(viewportSize.GetY()), m_backupSceneMatrices);
renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
renderer->SetState(g_defaultBlendState | g_defaultBaseState);
// remember the nesting level that we turned on 2D mode so we can turn it off as
// we unwind the stack
m_nestLevelAtWhichStarted2dMode = m_deferCallsFlagStack.size();
// Use scene associated with the specified viewport context
scene = m_viewportContext->GetRenderScene();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::EndDraw2d()
{
// if we are ending a non-deferred series of calls and we turned on 2D draw mode when we started
// this series then turn it off.
if (!m_deferCalls && m_nestLevelAtWhichStarted2dMode == m_deferCallsFlagStack.size())
else
{
IRenderer* renderer = gEnv->pRenderer;
renderer->Unset2DMode(m_backupSceneMatrices);
m_nestLevelAtWhichStarted2dMode = -1;
// No viewport context specified, use default scene
scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene();
}
// unwind the nesting stack
m_deferCalls = m_deferCallsFlagStack.top();
m_deferCallsFlagStack.pop();
AZ_Assert(scene != nullptr, "Attempting to create a DynamicDrawContext for a viewport context that has not been associated with a scene yet.");
// Create and initialize a DynamicDrawContext for 2d drawing
m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene.get());
AZ::RPI::ShaderOptionList shaderOptions;
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true")));
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("false")));
m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions);
m_dynamicDraw->InitVertexFormat(
{ {"POSITION", AZ::RHI::Format::R32G32B32_FLOAT},
{"COLOR", AZ::RHI::Format::B8G8R8A8_UNORM},
{"TEXCOORD0", AZ::RHI::Format::R32G32_FLOAT} });
m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::PrimitiveType
| AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode);
m_dynamicDraw->EndInit();
AZ::RHI::TargetBlendState targetBlendState;
targetBlendState.m_enable = true;
targetBlendState.m_blendSource = AZ::RHI::BlendFactor::AlphaSource;
targetBlendState.m_blendDest = AZ::RHI::BlendFactor::AlphaSourceInverse;
m_dynamicDraw->SetTarget0BlendState(targetBlendState);
// Cache draw srg input indices for later use
static const char textureIndexName[] = "m_texture";
static const char worldToProjIndexName[] = "m_worldToProj";
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = m_dynamicDraw->NewDrawSrg();
const AZ::RHI::ShaderResourceGroupLayout* layout = drawSrg->GetAsset()->GetLayout();
m_shaderData.m_imageInputIndex = layout->FindShaderInputImageIndex(AZ::Name(textureIndexName));
AZ_Error("Draw2d", m_shaderData.m_imageInputIndex.IsValid(), "Failed to find shader input constant %s.",
textureIndexName);
m_shaderData.m_viewProjInputIndex = layout->FindShaderInputConstantIndex(AZ::Name(worldToProjIndexName));
AZ_Error("Draw2d", m_shaderData.m_viewProjInputIndex.IsValid(), "Failed to find shader input constant %s.",
worldToProjIndexName);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Draw a textured quad with the top left corner at the given position.
void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity,
void CDraw2d::DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity,
float rotation, const AZ::Vector2* pivotPoint, const AZ::Vector2* minMaxTexCoords,
ImageOptions* imageOptions)
{
@ -169,7 +173,7 @@ void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float
quad.m_texCoords[3].Set(0.0f, 1.0f);
}
quad.m_texId = texId;
quad.m_image = image;
// add the blendMode flags to the base state
quad.m_state = blendMode | actualImageOptions->baseState;
@ -185,17 +189,17 @@ void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
void CDraw2d::DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size,
HAlign horizontalAlignment, VAlign verticalAlignment,
float opacity, float rotation, const AZ::Vector2* minMaxTexCoords, ImageOptions* imageOptions)
{
AZ::Vector2 alignedPosition = Align(position, size, horizontalAlignment, verticalAlignment);
DrawImage(texId, alignedPosition, size, opacity, rotation, &position, minMaxTexCoords, imageOptions);
DrawImage(image, alignedPosition, size, opacity, rotation, &position, minMaxTexCoords, imageOptions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState)
void CDraw2d::DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState)
{
int actualBlendMode = (blendMode == -1) ? g_defaultBlendState : blendMode;
int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState;
@ -208,7 +212,7 @@ void CDraw2d::DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding
quad.m_texCoords[i] = verts[i].uv;
quad.m_packedColors[i] = PackARGB8888(verts[i].color);
}
quad.m_texId = texId;
quad.m_image = image;
// add the blendMode flags to the base state
quad.m_state = actualBlendMode | actualBaseState;
@ -221,9 +225,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int
{
int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState;
IRenderer* renderer = gEnv->pRenderer;
int texId = renderer->GetWhiteTextureId();
auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
int actualBlendMode = (blendMode == -1) ? g_defaultBlendState : blendMode;
@ -231,7 +233,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int
uint32 packedColor = PackARGB8888(color);
DeferredLine line;
line.m_texId = texId;
line.m_image = image;
line.m_points[0] = Draw2dHelper::RoundXY(start, pixelRounding);
line.m_points[1] = Draw2dHelper::RoundXY(end, pixelRounding);
@ -250,7 +252,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState)
void CDraw2d::DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState)
{
int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState;
@ -258,7 +260,7 @@ void CDraw2d::DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode,
// define line
DeferredLine line;
line.m_texId = texId;
line.m_image = image;
for (int i = 0; i < 2; ++i)
{
@ -327,15 +329,19 @@ AZ::Vector2 CDraw2d::GetTextSize(const char* textString, float pointSize, TextOp
////////////////////////////////////////////////////////////////////////////////////////////////////
float CDraw2d::GetViewportWidth() const
{
IRenderer* renderer = gEnv->pRenderer;
return (float)renderer->GetOverlayWidth();
auto windowContext = GetViewportContext()->GetWindowContext();
const AZ::RHI::Viewport& viewport = windowContext->GetViewport();
const float viewWidth = viewport.m_maxX - viewport.m_minX;
return viewWidth;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float CDraw2d::GetViewportHeight() const
{
IRenderer* renderer = gEnv->pRenderer;
return (float)renderer->GetOverlayHeight();
auto windowContext = GetViewportContext()->GetWindowContext();
const AZ::RHI::Viewport& viewport = windowContext->GetViewport();
const float viewHeight = viewport.m_maxY - viewport.m_minY;
return viewHeight;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -353,27 +359,28 @@ const CDraw2d::TextOptions& CDraw2d::GetDefaultTextOptions() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::RenderDeferredPrimitives()
{
IRenderer* renderer = gEnv->pRenderer;
// Set up the 2D drawing state
renderer->SetCullMode(R_CULL_DISABLE);
renderer->Set2DMode(renderer->GetOverlayWidth(), renderer->GetOverlayHeight(), m_backupSceneMatrices);
renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
renderer->SetState(g_defaultBlendState | g_defaultBaseState);
// Draw and delete the deferred primitives
AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
for (auto primIter : m_deferredPrimitives)
{
primIter->Draw();
primIter->Draw(m_dynamicDraw, m_shaderData, viewportContext);
delete primIter;
}
// clear the list of deferred primitives
m_deferredPrimitives.clear();
}
// Reset the render state
renderer->Unset2DMode(m_backupSceneMatrices);
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::SetDeferPrimitives(bool deferPrimitives)
{
m_deferCalls = deferPrimitives;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool CDraw2d::GetDeferPrimitives()
{
return m_deferCalls;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -414,6 +421,30 @@ AZ::Vector2 CDraw2d::Align(AZ::Vector2 position, AZ::Vector2 size,
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::Data::Instance<AZ::RPI::Image> CDraw2d::LoadTexture(const AZStd::string& pathName)
{
AZStd::string sourceRelativePath(pathName);
AZStd::string cacheRelativePath = sourceRelativePath + ".streamingimage";
// The file may not be in the AssetCatalog at this point if it is still processing or doesn't exist on disk.
// Use GenerateAssetIdTEMP instead of GetAssetIdByPath so that it will return a valid AssetId anyways
AZ::Data::AssetId streamingImageAssetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
streamingImageAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP,
sourceRelativePath.c_str());
streamingImageAssetId.m_subId = AZ::RPI::StreamingImageAsset::GetImageAssetSubId();
auto streamingImageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset<AZ::RPI::StreamingImageAsset>(streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
AZ::Data::Instance<AZ::RPI::Image> image = AZ::RPI::StreamingImage::FindOrCreate(streamingImageAsset);
if (!image)
{
AZ_Error("Draw2d", false, "Failed to find or create an image instance from image asset '%s'", streamingImageAsset.GetHint().c_str());
}
return image;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// PROTECTED MEMBER FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -542,7 +573,7 @@ void CDraw2d::DrawOrDeferQuad(const DeferredQuad* quad)
}
else
{
quad->Draw();
quad->Draw(m_dynamicDraw, m_shaderData, GetViewportContext());
}
}
@ -557,16 +588,33 @@ void CDraw2d::DrawOrDeferLine(const DeferredLine* line)
}
else
{
line->Draw();
line->Draw(m_dynamicDraw, m_shaderData, GetViewportContext());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AZ::RPI::ViewportContextPtr CDraw2d::GetViewportContext() const
{
if (!m_viewportContext)
{
// Return the default viewport context
auto viewContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
return viewContextManager->GetDefaultViewportContext();
}
// Return the user specified viewport context
return m_viewportContext;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// CDraw2d::DeferredQuad
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DeferredQuad::Draw() const
void CDraw2d::DeferredQuad::Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const
{
const int32 NUM_VERTS = 6;
@ -585,17 +633,41 @@ void CDraw2d::DeferredQuad::Draw() const
vertices[i].st = Vec2(m_texCoords[j].GetX(), m_texCoords[j].GetY());
}
IRenderer* renderer = gEnv->pRenderer;
renderer->SetTexture(m_texId);
// Set up per draw SRG
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg();
// Set the render state, can't rely on this being right because font rendering changes it
renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
// Set texture
const AZ::RHI::ImageView* imageView = m_image ? m_image->GetImageView() : nullptr;
if (!imageView)
{
// Default to white texture
auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
imageView = image->GetImageView();
}
// set the desired render state
renderer->SetState(m_state);
if (imageView)
{
drawSrg->SetImageView(shaderData.m_imageInputIndex, imageView, 0);
}
// This will end up using DrawPrimitive to render the quad
renderer->DrawDynVB(vertices, nullptr, NUM_VERTS, 0, prtTriangleList);
// Set projection matrix
auto windowContext = viewportContext->GetWindowContext();
const AZ::RHI::Viewport& viewport = windowContext->GetViewport();
const float viewX = viewport.m_minX;
const float viewY = viewport.m_minY;
const float viewWidth = viewport.m_maxX - viewport.m_minX;
const float viewHeight = viewport.m_maxY - viewport.m_minY;
const float zf = viewport.m_minZ;
const float zn = viewport.m_maxZ;
AZ::Matrix4x4 modelViewProjMat;
AZ::MakeOrthographicMatrixRH(modelViewProjMat, viewX, viewX + viewWidth, viewY + viewHeight, viewY, zn, zf);
drawSrg->SetConstant(shaderData.m_viewProjInputIndex, modelViewProjMat);
drawSrg->Compile();
// Add the primitive to the dynamic draw context for drawing
dynamicDraw->SetPrimitiveType(AZ::RHI::PrimitiveTopology::TriangleList);
dynamicDraw->DrawLinear(vertices, NUM_VERTS, drawSrg);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -603,7 +675,9 @@ void CDraw2d::DeferredQuad::Draw() const
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DeferredLine::Draw() const
void CDraw2d::DeferredLine::Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
const Draw2dShaderData& shaderData,
AZ::RPI::ViewportContextPtr viewportContext) const
{
const float z = 1.0f; // depth test disabled, if writing Z this will write at far plane
@ -618,15 +692,41 @@ void CDraw2d::DeferredLine::Draw() const
vertices[i].st = Vec2(m_texCoords[i].GetX(), m_texCoords[i].GetY());
}
IRenderer* renderer = gEnv->pRenderer;
renderer->SetTexture(m_texId);
// Set up per draw SRG
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg();
// Set texture
const AZ::RHI::ImageView* imageView = m_image ? m_image->GetImageView() : nullptr;
if (!imageView)
{
// Default to white texture
auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
imageView = image->GetImageView();
}
// Set the render state, can't rely on this being right because font rendering changes it
renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
renderer->SetState(m_state);
if (imageView)
{
drawSrg->SetImageView(shaderData.m_imageInputIndex, imageView, 0);
}
// This will end up using DrawPrimitive to render the quad
renderer->DrawDynVB(vertices, nullptr, NUM_VERTS, 0, prtLineList);
// Set projection matrix
auto windowContext = viewportContext->GetWindowContext();
const AZ::RHI::Viewport& viewport = windowContext->GetViewport();
const float viewX = viewport.m_minX;
const float viewY = viewport.m_minY;
const float viewWidth = viewport.m_maxX - viewport.m_minX;
const float viewHeight = viewport.m_maxY - viewport.m_minY;
const float zf = viewport.m_minZ;
const float zn = viewport.m_maxZ;
AZ::Matrix4x4 modelViewProjMat;
AZ::MakeOrthographicMatrixRH(modelViewProjMat, viewX, viewX + viewWidth, viewY + viewHeight, viewY, zn, zf);
drawSrg->SetConstant(shaderData.m_viewProjInputIndex, modelViewProjMat);
drawSrg->Compile();
// Add the primitive to the dynamic draw context for drawing
dynamicDraw->SetPrimitiveType(AZ::RHI::PrimitiveTopology::LineList);
dynamicDraw->DrawLinear(vertices, NUM_VERTS, drawSrg);
}
@ -635,7 +735,9 @@ void CDraw2d::DeferredLine::Draw() const
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CDraw2d::DeferredText::Draw() const
void CDraw2d::DeferredText::Draw([[maybe_unused]] AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
[[maybe_unused]] const Draw2dShaderData& shaderData,
[[maybe_unused]] AZ::RPI::ViewportContextPtr viewportContext) const
{
m_font->DrawString(m_position.GetX(), m_position.GetY(), m_string.c_str(), true, m_fontContext);
}

@ -1,189 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <LyShine/IDraw2d.h>
#include <IRenderer.h>
#include <stack>
////////////////////////////////////////////////////////////////////////////////////////////////////
//! Implementation of IDraw2d interface for 2D drawing in screen space
//
//! The CDraw2d class implements the IDraw2d interface for drawing 2D images, shapes and text.
//! Positions and sizes are specified in pixels in the current 2D viewport.
class CDraw2d
: public IDraw2d
{
public: // member functions
//! Constructor, constructed by the LyShine class
CDraw2d();
// IDraw2d
~CDraw2d() override;
//! Start a section of 2D drawing function calls. This will set appropriate render state.
void BeginDraw2d(bool deferCalls = false) override;
//! Start a section of 2D drawing function calls. This will set appropriate render state.
//! This variant allows the viewport size to be specified
void BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls = false) override;
//! End a section of 2D drawing function calls. This will reset some render state.
void EndDraw2d() override;
//! Draw a textured quad, optional rotation is counter-clockwise in degrees.
void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f,
float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr) override;
//! Draw a textured quad where the position specifies the point specified by the alignment. Rotation is around that point.
void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size,
HAlign horizontalAlignment, VAlign verticalAlignment,
float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr,
ImageOptions* imageOptions = nullptr) override;
//! Draw a textured quad where the position, color and uv of each point is specified explicitly
void DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) override;
//! Draw a line
void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode, Rounding pixelRounding, int baseState) override;
//! Draw a line textured
void DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) override;
//! Draw a text string. Only supports ASCII text.
void DrawText(const char* textString, AZ::Vector2 position, float pointSize,
float opacity = 1.0f, TextOptions* textOptions = nullptr) override;
//! Get the width and height (in pixels) that would be used to draw the given text string.
AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr) override;
//! Get the width of the rendering viewport (in pixels).
float GetViewportWidth() const override;
//! Get the height of the rendering viewport (in pixels).
float GetViewportHeight() const override;
//! Get the default values that would be used if no image options were passed in
const ImageOptions& GetDefaultImageOptions() const override;
//! Get the default values that would be used if no text options were passed in
const TextOptions& GetDefaultTextOptions() const override;
// ~IDraw2d
//! Render the primitives that have been deferred
void RenderDeferredPrimitives();
private:
AZ_DISABLE_COPY_MOVE(CDraw2d);
public: // static member functions
//! Given a position and size and an alignment return the top left corner of the aligned quad
static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment);
protected: // types and constants
enum
{
MAX_VERTICES_IN_PRIM = 6
};
class DeferredPrimitive
{
public:
virtual ~DeferredPrimitive() {};
virtual void Draw() const = 0;
};
class DeferredQuad
: public DeferredPrimitive
{
public:
~DeferredQuad() override {};
void Draw() const override;
AZ::Vector2 m_points[4];
AZ::Vector2 m_texCoords[4];
uint32 m_packedColors[4];
int m_texId;
int m_state;
};
class DeferredLine
: public DeferredPrimitive
{
public:
~DeferredLine() override {};
void Draw() const override;
int m_texId;
AZ::Vector2 m_points[2];
AZ::Vector2 m_texCoords[2];
uint32 m_packedColors[2];
int m_state;
};
class DeferredText
: public DeferredPrimitive
{
public:
~DeferredText() override {};
void Draw() const override;
STextDrawContext m_fontContext;
IFFont* m_font;
AZ::Vector2 m_position;
std::string m_string;
};
protected: // member functions
//! Rotate an array of points around the z-axis at the pivot point.
//
//! Angle is in degrees counter-clockwise
void RotatePointsAboutPivot(AZ::Vector2* points, int numPoints, AZ::Vector2 pivot, float angle) const;
//! Helper function to render a text string
void DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex,
AZ::Vector2 position, float pointSize, AZ::Color color, float rotation,
HAlign horizontalAlignment, VAlign verticalAlignment, int baseState);
//! Draw or defer a quad
void DrawOrDeferQuad(const DeferredQuad* quad);
//! Draw or defer a line
void DrawOrDeferLine(const DeferredLine* line);
protected: // attributes
ImageOptions m_defaultImageOptions; //!< The default image options used if nullptr is passed
TextOptions m_defaultTextOptions; //!< The default text options used if nullptr is passed
bool m_deferCalls; //!< True if the actual render of the primitives should be deferred until end of frame
std::vector<DeferredPrimitive*> m_deferredPrimitives;
//! These two data members allows nested calls to BeginDraw2d/EndDraw2d. We will begin 2D mode only on the
//! outermost call to BeginDraw2d with deferCalls set to false and will end 2D mode on the corresposnding
//! call to EndDraw2d. The stack is used to detect that corresponding call and we need the level it occurred
//! to know when to end 2D mode.
int m_nestLevelAtWhichStarted2dMode;
std::stack<bool> m_deferCallsFlagStack;
private:
TransformationMatrices m_backupSceneMatrices;
};

@ -13,8 +13,6 @@
#include "LyShine.h"
#include "Draw2d.h"
#include "UiCanvasComponent.h"
#include "UiCanvasManager.h"
#include "LyShineDebug.h"
@ -55,6 +53,7 @@
#include <LyShine/Bus/UiCursorBus.h>
#include <LyShine/Bus/UiDraggableBus.h>
#include <LyShine/Bus/UiDropTargetBus.h>
#include <LyShine/Draw2d.h>
#if defined(LYSHINE_INTERNAL_UNIT_TEST)
#include "TextMarkup.h"
@ -455,7 +454,6 @@ void CLyShine::Render()
// Render all the canvases loaded in game
m_uiCanvasManager->RenderLoadedCanvases();
#ifdef LYSHINE_ATOM_TODO // convert cursor support to use Atom
m_draw2d->RenderDeferredPrimitives();
// Don't render the UI cursor when in edit mode. For example during UI Preview mode a script could turn on the
@ -466,7 +464,6 @@ void CLyShine::Render()
{
RenderUiCursor();
}
#endif
GetUiRenderer()->EndUiFrameRender();
@ -687,9 +684,11 @@ void CLyShine::RenderUiCursor()
const AZ::Vector2 position = GetUiCursorPosition();
const AZ::Vector2 dimensions(static_cast<float>(m_uiCursorTexture->GetWidth()), static_cast<float>(m_uiCursorTexture->GetHeight()));
#ifdef LYSHINE_ATOM_TODO // Convert cursor to Atom image
m_draw2d->BeginDraw2d();
m_draw2d->DrawImage(m_uiCursorTexture->GetTextureID(), position, dimensions);
m_draw2d->EndDraw2d();
#endif
}
#ifndef _RELEASE

@ -12,8 +12,9 @@
#include "LyShine_precompiled.h"
#include "LyShineDebug.h"
#include "IConsole.h"
#include <LyShine/IDraw2d.h>
#include "IRenderer.h"
#include <LyShine/Draw2d.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Serialization/SerializeContext.h>
@ -105,15 +106,24 @@ static bool g_deferDrawsToEndOfFrame = false;
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
#ifdef LYSHINE_ATOM_TODO
static int Create2DTexture(int width, int height, byte* data, ETEX_Format format)
{
IRenderer* renderer = gEnv->pRenderer;
return renderer->DownLoadToVideoMemory(data, width, height, format, format, 1);
}
#endif
#endif
static AZ::Vector2 GetTextureSize(AZ::Data::Instance<AZ::RPI::Image> image)
{
AZ::RHI::Size size = image->GetDescriptor().m_size;
return AZ::Vector2(size.m_width, size.m_height);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
#ifdef LYSHINE_ATOM_TODO
static void FillTextureRectWithCheckerboard(uint32* data, int textureWidth, int textureHeight,
int minX, int minY, [[maybe_unused]] int rectWidth, int rectHeight,
int tileWidth, int tileHeight, uint32* colors, bool varyAlpha)
@ -139,11 +149,13 @@ static void FillTextureRectWithCheckerboard(uint32* data, int textureWidth, int
}
}
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* CreateMonoTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> CreateMonoTestTexture()
{
#ifdef LYSHINE_ATOM_TODO
const int width = 32;
const int height = 32;
uint32 data[width * height];
@ -172,13 +184,18 @@ static ITexture* CreateMonoTestTexture()
int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8);
return gEnv->pRenderer->EF_GetTextureByID(textureId);
#else
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
return whiteTexture;
#endif
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* CreateColorTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> CreateColorTestTexture()
{
#ifdef LYSHINE_ATOM_TODO
const int width = 32;
const int height = 32;
uint32 data[width * height];
@ -207,13 +224,18 @@ static ITexture* CreateColorTestTexture()
int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8);
return gEnv->pRenderer->EF_GetTextureByID(textureId);
#else
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
return whiteTexture;
#endif
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* CreateMonoAlphaTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> CreateMonoAlphaTestTexture()
{
#ifdef LYSHINE_ATOM_TODO
const int width = 32;
const int height = 32;
uint32 data[width * height];
@ -242,13 +264,18 @@ static ITexture* CreateMonoAlphaTestTexture()
int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8);
return gEnv->pRenderer->EF_GetTextureByID(textureId);
#else
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
return whiteTexture;
#endif
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* CreateColorAlphaTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> CreateColorAlphaTestTexture()
{
#ifdef LYSHINE_ATOM_TODO
const int width = 32;
const int height = 32;
uint32 data[width * height];
@ -277,14 +304,18 @@ static ITexture* CreateColorAlphaTestTexture()
int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8);
return gEnv->pRenderer->EF_GetTextureByID(textureId);
#else
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
return whiteTexture;
#endif
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* GetMonoTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> GetMonoTestTexture()
{
static ITexture* testImageMono = nullptr;
static AZ::Data::Instance<AZ::RPI::Image> testImageMono = nullptr;
if (!testImageMono)
{
@ -297,9 +328,9 @@ static ITexture* GetMonoTestTexture()
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* GetColorTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> GetColorTestTexture()
{
static ITexture* testImageColor = nullptr;
static AZ::Data::Instance<AZ::RPI::Image> testImageColor = nullptr;
if (!testImageColor)
{
@ -312,9 +343,9 @@ static ITexture* GetColorTestTexture()
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* GetMonoAlphaTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> GetMonoAlphaTestTexture()
{
static ITexture* testImageMonoAlpha = nullptr;
static AZ::Data::Instance<AZ::RPI::Image> testImageMonoAlpha = nullptr;
if (!testImageMonoAlpha)
{
@ -327,9 +358,9 @@ static ITexture* GetMonoAlphaTestTexture()
////////////////////////////////////////////////////////////////////////////////////////////////////
#if !defined(_RELEASE)
static ITexture* GetColorAlphaTestTexture()
static AZ::Data::Instance<AZ::RPI::Image> GetColorAlphaTestTexture()
{
static ITexture* testImageColorAlpha = nullptr;
static AZ::Data::Instance<AZ::RPI::Image> testImageColorAlpha = nullptr;
if (!testImageColorAlpha)
{
@ -347,14 +378,12 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col
IDraw2d::HAlign horizontalAlignment = IDraw2d::HAlign::Left,
IDraw2d::VAlign verticalAlignment = IDraw2d::VAlign::Top)
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
IRenderer* renderer = gEnv->pRenderer;
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
int whiteTextureId = renderer->GetWhiteTextureId();
imageOptions.color = color.GetAsVector3();
draw2d->DrawImageAligned(whiteTextureId, pos, size, horizontalAlignment, verticalAlignment,
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
draw2d->DrawImageAligned(whiteTexture, pos, size, horizontalAlignment, verticalAlignment,
color.GetA(), 0.0f, nullptr, &imageOptions);
}
#endif
@ -364,7 +393,7 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col
static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, const char* sizeString,
const char* testString, AZ::Vector2 pos, float spacing, float size)
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions();
if (font)
@ -398,9 +427,7 @@ static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, c
#if !defined(_RELEASE)
static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const char* fontName)
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
float xOffset = 20.0f;
float yOffset = 20.0f;
@ -463,8 +490,6 @@ static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const c
yOffset += 55.0f;
DebugDrawStringWithSizeBox(font, effectIndex, "Size 49", testString, AZ::Vector2(xOffset, yOffset), xSpacing, 49);
draw2d->EndDraw2d();
}
#endif
@ -524,7 +549,7 @@ static void DebugDrawAlignedTextWithOriginBox(AZ::Vector2 pos,
#if !defined(_RELEASE)
static void DebugDraw2dFontAlignment()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
float w = draw2d->GetViewportWidth();
float yPos = 20;
@ -591,7 +616,7 @@ static void DebugDraw2dFontAlignment()
#if !defined(_RELEASE)
static AZ::Vector2 DebugDrawFontColorTestBox(AZ::Vector2 pos, const char* string, AZ::Vector3 color, float opacity)
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
float pointSize = 32.0f;
const float spacing = 6.0f;
@ -626,9 +651,7 @@ static AZ::Vector2 DebugDrawFontColorTestBox(AZ::Vector2 pos, const char* string
#if !defined(_RELEASE)
static void DebugDraw2dFontColorAndOpacity()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
AZ::Vector2 size;
AZ::Vector2 pos(20.0f, 20.0f);
@ -659,8 +682,6 @@ static void DebugDraw2dFontColorAndOpacity()
draw2d->DrawText("Opacity=0.25f", pos, 24.0f);
pos.SetX(pos.GetX() + 200.0f);
draw2d->DrawText("Opacity=0.00f", pos, 24.0f);
draw2d->EndDraw2d();
}
#endif
@ -668,16 +689,11 @@ static void DebugDraw2dFontColorAndOpacity()
#if !defined(_RELEASE)
static void DebugDraw2dImageRotations()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
ITexture* texture = GetMonoTestTexture();
int texId = texture->GetTextureID();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
AZ::Data::Instance<AZ::RPI::Image> texture = GetMonoTestTexture();
float width = (float)texture->GetWidth();
float height = (float)texture->GetHeight();
AZ::Vector2 size(width, height);
AZ::Vector2 size = GetTextureSize(texture);
float row = 20.0f;
float xSpacing = size.GetX() * 2.0f;
@ -690,7 +706,7 @@ static void DebugDraw2dImageRotations()
for (int i = 0; i < 10; ++i)
{
AZ::Vector2 pos(xStart + xSpacing * i, row);
draw2d->DrawImage(texId, pos, size, 1.0f, 45.0f * i);
draw2d->DrawImage(texture, pos, size, 1.0f, 45.0f * i);
DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor);
}
@ -703,7 +719,7 @@ static void DebugDraw2dImageRotations()
{
AZ::Vector2 pos(xStart + xSpacing * i, row);
AZ::Vector2 pivot = pos + pivotOffset;
draw2d->DrawImage(texId, pos, size, 1.0f, 45.0f * i, &pivot);
draw2d->DrawImage(texture, pos, size, 1.0f, 45.0f * i, &pivot);
DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor);
DebugDrawColoredBox(AZ::Vector2(pivot.GetX() - 2, pivot.GetY() - 2), AZ::Vector2(5, 5), pivotBoxColor);
}
@ -715,11 +731,9 @@ static void DebugDraw2dImageRotations()
for (int i = 0; i < 10; ++i)
{
AZ::Vector2 pos(xStart + xSpacing * i + size.GetX() * 0.5f, row + size.GetY() * 0.5f);
draw2d->DrawImageAligned(texId, pos, size, IDraw2d::HAlign::Center, IDraw2d::VAlign::Center, 1.0f, 45.0f * i);
draw2d->DrawImageAligned(texture, pos, size, IDraw2d::HAlign::Center, IDraw2d::VAlign::Center, 1.0f, 45.0f * i);
DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor);
}
draw2d->EndDraw2d();
}
#endif
@ -727,22 +741,17 @@ static void DebugDraw2dImageRotations()
#if !defined(_RELEASE)
static void DebugDraw2dImageColor()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
ITexture* texture = GetMonoAlphaTestTexture();
int texId = texture->GetTextureID();
AZ::Data::Instance<AZ::RPI::Image> texture = GetMonoAlphaTestTexture();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
draw2d->DrawText(
"Testing image colors, image is black and white, top row is opacity=1, bottom row is opacity = 0.5",
AZ::Vector2(20, 20), 16);
float width = texture->GetWidth() * 2.0f;
float height = texture->GetHeight() * 2.0f;
AZ::Vector2 size(width, height);
AZ::Vector2 size = GetTextureSize(texture) * 2.0f;
float xStart = 20.0f;
float yStart = 50.0f;
@ -755,14 +764,12 @@ static void DebugDraw2dImageColor()
// Draw the image with this color
imageOptions.color = g_colorVec3[color];
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
// draw below with half opacity to test combination of color and opacity
pos.SetY(pos.GetY() + ySpacing);
draw2d->DrawImage(texId, pos, size, 0.5f, 0.0f, 0, 0, &imageOptions);
draw2d->DrawImage(texture, pos, size, 0.5f, 0.0f, 0, 0, &imageOptions);
}
draw2d->EndDraw2d();
}
#endif
@ -770,24 +777,20 @@ static void DebugDraw2dImageColor()
#if !defined(_RELEASE)
static void DebugDraw2dImageBlendMode()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
IRenderer* renderer = gEnv->pRenderer;
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
int whiteTextureId = renderer->GetWhiteTextureId();
auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White);
ITexture* texture = GetColorAlphaTestTexture();
int texId = texture->GetTextureID();
AZ::Data::Instance<AZ::RPI::Image> texture = GetColorAlphaTestTexture();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
draw2d->DrawText("Testing blend modes, src blend changes across x-axis, dst blend changes across y axis",
AZ::Vector2(20, 20), 16);
float width = (float)texture->GetWidth();
float height = (float)texture->GetHeight();
AZ::Vector2 size(width, height);
AZ::Vector2 size = GetTextureSize(texture);
float width = size.GetX();
float height = size.GetY();
float xStart = 20.0f;
float yStart = 60.0f;
@ -824,16 +827,14 @@ static void DebugDraw2dImageBlendMode()
AZ::Vector2(0.0f, 1.0f)
},
};
draw2d->DrawQuad(whiteTextureId, verts);
draw2d->DrawQuad(whiteTexture, verts);
// Draw the image with this color
imageOptions.blendMode = g_srcBlendModes[srcIndex] | g_dstBlendModes[dstIndex];
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
}
}
draw2d->EndDraw2d();
}
#endif
@ -841,20 +842,17 @@ static void DebugDraw2dImageBlendMode()
#if !defined(_RELEASE)
static void DebugDraw2dImageUVs()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
ITexture* texture = GetColorTestTexture();
int texId = texture->GetTextureID();
AZ::Data::Instance<AZ::RPI::Image> texture = GetColorTestTexture();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
draw2d->DrawText(
"Testing DrawImage with minMaxTexCoords. Full image, top left quadrant, middle section, full flipped",
AZ::Vector2(20, 20), 16);
AZ::Vector2 size((float)texture->GetWidth() * 2.0f, (float)texture->GetHeight() * 2.0f);
AZ::Vector2 size = GetTextureSize(texture) * 2.0f;
float xStart = 20.0f;
float yStart = 50.0f;
@ -867,27 +865,25 @@ static void DebugDraw2dImageUVs()
// full image
minMaxTexCoords[0] = AZ::Vector2(0, 0);
minMaxTexCoords[1] = AZ::Vector2(1, 1);
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
// top left quadrant of image
pos.SetX(pos.GetX() + xSpacing);
minMaxTexCoords[0] = AZ::Vector2(0, 0);
minMaxTexCoords[1] = AZ::Vector2(0.5, 0.5);
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
// middle of image
pos.SetX(pos.GetX() + xSpacing);
minMaxTexCoords[0] = AZ::Vector2(0.25, 0.25);
minMaxTexCoords[1] = AZ::Vector2(0.75, 0.75);
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
// flip of image
pos.SetX(pos.GetX() + xSpacing);
minMaxTexCoords[0] = AZ::Vector2(0.0, 1.0);
minMaxTexCoords[1] = AZ::Vector2(1.0, 0.0);
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
draw2d->EndDraw2d();
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords);
}
#endif
@ -895,18 +891,15 @@ static void DebugDraw2dImageUVs()
#if !defined(_RELEASE)
static void DebugDraw2dImagePixelRounding()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
ITexture* texture = GetColorTestTexture();
int texId = texture->GetTextureID();
AZ::Data::Instance<AZ::RPI::Image> texture = GetColorTestTexture();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
draw2d->DrawText("Testing DrawImage pixel rounding options", AZ::Vector2(20, 20), 16);
AZ::Vector2 size((float)texture->GetWidth(), (float)texture->GetHeight());
AZ::Vector2 size = GetTextureSize(texture);
float xStart = 20.0f;
float yStart = 50.0f;
@ -929,11 +922,9 @@ static void DebugDraw2dImagePixelRounding()
imageOptions.pixelRounding = roundings[j];
draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions);
}
}
draw2d->EndDraw2d();
}
#endif
@ -941,12 +932,10 @@ static void DebugDraw2dImagePixelRounding()
#if !defined(_RELEASE)
static void DebugDraw2dLineBasic()
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions();
draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame);
draw2d->DrawText("Testing DrawLine", AZ::Vector2(20, 20), 16);
AZ::Vector2 center = AZ::Vector2(draw2d->GetViewportWidth() * 0.5f, draw2d->GetViewportHeight() * 0.5f);
@ -963,8 +952,6 @@ static void DebugDraw2dLineBasic()
draw2d->DrawLine(center, center + AZ::Vector2(-offset, -offset), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f));
draw2d->DrawLine(center, center + AZ::Vector2(0, -offset), AZ::Color(1.0f, 0.0f, 1.0f, 1.0f));
draw2d->DrawLine(center, center + AZ::Vector2(offset, -offset), AZ::Color(0.0f, 0.0f, 0.0f, 1.0f));
draw2d->EndDraw2d();
}
#endif
@ -1436,13 +1423,17 @@ void LyShineDebug::RenderDebug()
#if !defined(_RELEASE)
#ifndef EXCLUDE_DOCUMENTATION_PURPOSE
if (!Draw2dHelper::GetDraw2d())
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
if (!draw2d)
{
return;
}
g_deferDrawsToEndOfFrame = (CV_r_DebugUIDraw2dDefer) ? true : false;
// Set whether to defer draws or render immediately during scope of this helper
Draw2dHelper draw2dHelper(g_deferDrawsToEndOfFrame);
if (CV_r_DebugUIDraw2dFont)
{
switch (CV_r_DebugUIDraw2dFont)

@ -33,6 +33,7 @@
#include <LyShine/Bus/UiEntityContextBus.h>
#include <LyShine/Bus/UiCanvasUpdateNotificationBus.h>
#include <LyShine/UiSerializeHelpers.h>
#include <LyShine/Draw2d.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Memory/Memory.h>
@ -2224,13 +2225,13 @@ void UiCanvasComponent::DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LySh
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasComponent::DebugDisplayElemBounds(IDraw2d* draw2d) const
void UiCanvasComponent::DebugDisplayElemBounds(CDraw2d* draw2d) const
{
DebugDisplayChildElemBounds(draw2d, m_rootElement);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasComponent::DebugDisplayChildElemBounds(IDraw2d* draw2d, const AZ::EntityId entity) const
void UiCanvasComponent::DebugDisplayChildElemBounds(CDraw2d* draw2d, const AZ::EntityId entity) const
{
AZ::u64 time = AZStd::GetTimeUTCMilliSecond();
uint32 fractionsOfOneSecond = time % 1000;

@ -42,6 +42,7 @@ namespace AZ
}
struct SDepthTexture;
class CDraw2d;
////////////////////////////////////////////////////////////////////////////////////////////////////
class UiCanvasComponent
@ -287,8 +288,8 @@ public: // member functions
void DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LyShineDebug::DebugInfoDrawCallReport& reportInfo, void* context) const;
void DebugDisplayElemBounds(IDraw2d* draw2d) const;
void DebugDisplayChildElemBounds(IDraw2d* draw2d, const AZ::EntityId entity) const;
void DebugDisplayElemBounds(CDraw2d* draw2d) const;
void DebugDisplayChildElemBounds(CDraw2d* draw2d, const AZ::EntityId entity) const;
#endif
public: // static member functions

@ -11,6 +11,7 @@
*/
#include "LyShine_precompiled.h"
#include "UiCanvasManager.h"
#include <LyShine/Draw2d.h>
#include "UiCanvasFileObject.h"
#include "UiCanvasComponent.h"
@ -33,6 +34,8 @@
#include <LyShine/Bus/World/UiCanvasOnMeshBus.h>
#include <LyShine/Bus/World/UiCanvasRefBus.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#ifndef _RELEASE
#include <AzFramework/IO/LocalFileIO.h>
#endif
@ -998,16 +1001,15 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const
{
bool onlyShowEnabledCanvases = (setting == 2) ? true : false;
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
draw2d->BeginDraw2d(false);
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
float xOffset = 20.0f;
float yOffset = 20.0f;
const int elementNameFieldLength = 20;
int blackTexture = gEnv->pRenderer->GetBlackTextureId();
auto blackTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Black);
float textOpacity = 1.0f;
float backgroundRectOpacity = 0.75f;
@ -1152,21 +1154,17 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const
totalEnabledIntrs, totalEnabledUpdates);
WriteLine(buffer, red);
draw2d->EndDraw2d();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasManager::DebugDisplayDrawCallData() const
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
draw2d->BeginDraw2d(false);
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
float xOffset = 20.0f;
float yOffset = 20.0f;
int blackTexture = gEnv->pRenderer->GetBlackTextureId();
auto blackTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Black);
float textOpacity = 1.0f;
float backgroundRectOpacity = 0.75f;
const float lineSpacing = 20.0f;
@ -1293,8 +1291,6 @@ void UiCanvasManager::DebugDisplayDrawCallData() const
totalDueToMaxVerts, totalDueToTextures);
WriteLine(buffer, red);
draw2d->EndDraw2d();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1492,9 +1488,7 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const
////////////////////////////////////////////////////////////////////////////////////////////////////
void UiCanvasManager::DebugDisplayElemBounds(int canvasIndexFilter) const
{
IDraw2d* draw2d = Draw2dHelper::GetDraw2d();
draw2d->BeginDraw2d(false);
CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d();
int canvasIndex = 0;
for (auto canvas : m_loadedCanvases)
@ -1515,8 +1509,6 @@ void UiCanvasManager::DebugDisplayElemBounds(int canvasIndexFilter) const
++canvasIndex; // only increments for enabled canvases so index matches "ui_DisplayCanvasData 2"
}
draw2d->EndDraw2d();
}
#endif

@ -11,6 +11,7 @@
*/
#include "LyShine_precompiled.h"
#include "UiFaderComponent.h"
#include <LyShine/Draw2d.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Math/MathUtils.h>

@ -20,7 +20,7 @@
#include <IRenderer.h>
#include <LyShine/IDraw2d.h>
#include <LyShine/Draw2d.h>
#include <LyShine/UiSerializeHelpers.h>
#include <LyShine/Bus/UiElementBus.h>
#include <LyShine/Bus/UiCanvasBus.h>

@ -12,7 +12,7 @@
#include "LyShine_precompiled.h"
#include "UiImageSequenceComponent.h"
#include <LyShine/IDraw2d.h>
#include <LyShine/Draw2d.h>
#include <LyShine/ISprite.h>
#include <LyShine/IRenderGraph.h>
#include <LyShine/Bus/UiElementBus.h>

@ -11,6 +11,7 @@
*/
#include "LyShine_precompiled.h"
#include "UiMaskComponent.h"
#include <LyShine/Draw2d.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Serialization/SerializeContext.h>
@ -23,7 +24,6 @@
#include <LyShine/Bus/UiRenderBus.h>
#include <LyShine/Bus/UiVisualBus.h>
#include <LyShine/Bus/UiCanvasBus.h>
#include <LyShine/IDraw2d.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC MEMBER FUNCTIONS

@ -28,11 +28,11 @@
#include <LyShine/Bus/UiCanvasBus.h>
#include <LyShine/UiSerializeHelpers.h>
#include <LyShine/IRenderGraph.h>
#include <LyShine/Draw2d.h>
#include <ILocalizationManager.h>
#include "UiSerialize.h"
#include "Draw2d.h"
#include "TextMarkup.h"
#include "UiTextComponentOffsetsSelector.h"
#include "StringUtfUtils.h"

@ -11,7 +11,7 @@
set(FILES
Source/Draw2d.cpp
Source/Draw2d.h
Include/LyShine/Draw2d.h
Source/LyShine.cpp
Source/LyShine.h
Source/LyShineDebug.cpp

@ -23,6 +23,7 @@ ly_add_target(
PUBLIC
Legacy::CryCommon
Gem::LmbrCentral
Gem::LyShine.Static
)
ly_add_target(

@ -20,7 +20,7 @@
#include <IRenderer.h>
#include <LyShine/IDraw2d.h>
#include <LyShine/Draw2d.h>
#include <LyShine/ISprite.h>
#include <LyShine/Bus/UiElementBus.h>
#include <LyShine/Bus/UiCanvasBus.h>

Loading…
Cancel
Save