diff --git a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h index e71c8421d3..16fdfceca3 100644 --- a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h +++ b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h @@ -11,7 +11,7 @@ */ #pragma once -#include +#include #include #include #include @@ -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 - 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; }; diff --git a/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h b/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h deleted file mode 100644 index 797ea51b87..0000000000 --- a/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h +++ /dev/null @@ -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 - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//! 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(); } -}; diff --git a/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h b/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h index 131671e2a5..91b5cc294c 100644 --- a/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h +++ b/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h @@ -20,6 +20,7 @@ #include #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index 76df971108..6cea9324c4 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -2298,6 +2298,12 @@ namespace AzQtComponents OptimizedSetParent(dock, mainWindow); mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); dock->show(); + + // Make sure we listen for events on the dock widget being put into a floating dock window + // because this might be called programmatically, so the dock widget might have never been + // parented to our m_mainWindow initially, so it won't already have an event filter, + // which will prevent the docking functionality from working. + dock->installEventFilter(this); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index f12ab71936..cca5d1b9e4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -815,8 +815,6 @@ namespace AzToolsFramework /// Hide or show the circular dependency error when saving slices virtual void SetShowCircularDependencyError(const bool& /*showCircularDependencyError*/) {} - virtual void SetEditTool(const char* /*tool*/) {} - /// Launches the Lua editor and opens the specified (space separated) files. virtual void LaunchLuaEditor(const char* /*files*/) {} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index 0a25d1cf25..abc290a406 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -140,7 +140,7 @@ namespace AzToolsFramework else { QPixmap pixmap = thumbnail->GetPixmap(size); - painter->drawPixmap(point.x(), point.y(), size.width(), size.height(), pixmap); + painter->drawPixmap(point, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } return m_iconSize; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp index 939ca813b6..2892e4efce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp @@ -10,12 +10,14 @@ * */ +#include #include AZ_PUSH_DISABLE_WARNING(4127 4251 4800 4244, "-Wunknown-warning-option") // 4127: conditional expression is constant // 4251: 'QTextCodec::ConverterState::flags': class 'QFlags' needs to have dll-interface to be used by clients of struct 'QTextCodec::ConverterState' // 4800: 'QTextBoundaryFinderPrivate *const ': forcing value to bool 'true' or 'false' (performance warning) // 4244: conversion from 'int' to 'qint8', possible loss of data #include +#include AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -80,7 +82,11 @@ namespace AzToolsFramework if (m_state == State::Unloaded) { m_state = State::Loading; - QFuture future = QtConcurrent::run([this](){ LoadThread(); }); + QThreadPool* threadPool; + ThumbnailContextRequestBus::BroadcastResult( + threadPool, + &ThumbnailContextRequestBus::Handler::GetThreadPool); + QFuture future = QtConcurrent::run(threadPool, [this](){ LoadThread(); }); m_watcher.setFuture(future); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp index 8f6b9c63fd..ae6d7c1178 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp @@ -28,10 +28,15 @@ namespace AzToolsFramework : m_missingThumbnail(new MissingThumbnail(thumbnailSize)) , m_loadingThumbnail(new LoadingThumbnail(thumbnailSize)) , m_thumbnailSize(thumbnailSize) + , m_threadPool(this) { + ThumbnailContextRequestBus::Handler::BusConnect(); } - ThumbnailContext::~ThumbnailContext() = default; + ThumbnailContext::~ThumbnailContext() + { + ThumbnailContextRequestBus::Handler::BusDisconnect(); + } bool ThumbnailContext::IsLoading(SharedThumbnailKey key) { @@ -53,6 +58,11 @@ namespace AzToolsFramework AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetBrowserViewRequests::Update); } + QThreadPool* ThumbnailContext::GetThreadPool() + { + return &m_threadPool; + } + SharedThumbnail ThumbnailContext::GetThumbnail(SharedThumbnailKey key) { SharedThumbnail thumbnail; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h index 589abad0df..6ba3d637f6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h @@ -19,6 +19,7 @@ #include #include +#include #endif class QString; @@ -40,6 +41,7 @@ namespace AzToolsFramework */ class ThumbnailContext : public QObject + , public ThumbnailContextRequestBus::Handler { Q_OBJECT public: @@ -58,10 +60,13 @@ namespace AzToolsFramework void UnregisterThumbnailProvider(const char* providerName); void RedrawThumbnail(); - + //! Default context used for most thumbnails static constexpr const char* DefaultContext = "Default"; + // ThumbnailContextRequestBus::Handler interface overrides... + QThreadPool* GetThreadPool() override; + private: struct ProviderCompare { bool operator() (const SharedThumbnailProvider& lhs, const SharedThumbnailProvider& rhs) const @@ -79,6 +84,9 @@ namespace AzToolsFramework SharedThumbnail m_loadingThumbnail; //! Thumbnail size (width and height in pixels) int m_thumbnailSize; + //! There is only a limited number of threads on global threadPool, because there can be many thumbnails rendering at once + //! an individual threadPool is needed to avoid deadlocks + QThreadPool m_threadPool; }; } // namespace Thumbnailer } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp index 1aefa6f189..038bfd5da5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp @@ -81,6 +81,9 @@ namespace AzToolsFramework int x = (originalWidth - realWidth) / 2; // pixmap needs to be manually scaled to produce smoother result and avoid looking pixelated // using painter.setRenderHint(QPainter::SmoothPixmapTransform); does not seem to work + // Note: there is a potential issue with pixmap.scaled: + // it is multithreaded (using global threadPool) and blocking until finished. + // A deadlock will happen if global threadPool has no free threads available. painter.drawPixmap(QPoint(x, 0), pixmap.scaled(realWidth, realHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } QWidget::paintEvent(event); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h index ebc721bb4c..02264e61f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h @@ -17,11 +17,23 @@ #include class QPixmap; +class QThreadPool; namespace AzToolsFramework { namespace Thumbnailer { + //! Interaction with thumbnail context + class ThumbnailContextRequests + : public AZ::EBusTraits + { + public: + //! Get thread pool for drawing thumbnails + virtual QThreadPool* GetThreadPool() = 0; + }; + + using ThumbnailContextRequestBus = AZ::EBus; + //! Interaction with thumbnailer class ThumbnailerRequests : public AZ::EBusTraits diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp index 8cc6d46da8..0aec36b9b0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp @@ -192,6 +192,10 @@ namespace LegacyFramework // if we're in console mode, listen for CTRL+C ::SetConsoleCtrlHandler(CTRL_BREAK_HandlerRoutine, true); #endif + + m_ptrCommandLineParser = aznew AzFramework::CommandLine(); + m_ptrCommandLineParser->Parse(m_desc.m_argc, m_desc.m_argv); + // If we don't have one create a serialize context if (GetSerializeContext() == nullptr) { diff --git a/Code/Sandbox/Editor/2DViewport.cpp b/Code/Sandbox/Editor/2DViewport.cpp index e6e62be1f1..d86ea03bdf 100644 --- a/Code/Sandbox/Editor/2DViewport.cpp +++ b/Code/Sandbox/Editor/2DViewport.cpp @@ -20,7 +20,6 @@ #include "2DViewport.h" #include "CryEditDoc.h" #include "DisplaySettings.h" -#include "EditTool.h" #include "GameEngine.h" #include "Settings.h" #include "ViewManager.h" @@ -1117,11 +1116,6 @@ void Q2DViewport::DrawObjects(DisplayContext& dc) GetIEditor()->GetObjectManager()->Display(dc); } - // Display editing tool. - if (GetEditTool()) - { - GetEditTool()->Display(dc); - } dc.PopMatrix(); } diff --git a/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp b/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp deleted file mode 100644 index ea91bdcd62..0000000000 --- a/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "EditorDefs.h" - -#include "QRollupCtrl.h" - -// Qt -#include -#include -#include -#include -#include -#include - -////////////////////////////////////////////////////////////////////////// - -class QRollupCtrlButton - : public QToolButton -{ -public: - QRollupCtrlButton(QWidget* parent); - - inline void setSelected(bool b) { selected = b; update(); } - inline bool isSelected() const { return selected; } - - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - -protected: - void paintEvent(QPaintEvent*) override; - -private: - bool selected; -}; - -QRollupCtrlButton::QRollupCtrlButton(QWidget* parent) - : QToolButton(parent) - , selected(true) -{ - setBackgroundRole(QPalette::Window); - setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - setFocusPolicy(Qt::NoFocus); - - setStyleSheet("* {margin: 2px 5px 2px 5px; border: 1px solid #CBA457;}"); -} - -QSize QRollupCtrlButton::sizeHint() const -{ - QSize iconSize(8, 8); - if (!icon().isNull()) - { - int icone = style()->pixelMetric(QStyle::PM_SmallIconSize); - iconSize += QSize(icone + 2, icone); - } - QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text()) + QSize(0, 8); - - QSize total(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height())); - return total.expandedTo(QApplication::globalStrut()); -} - -QSize QRollupCtrlButton::minimumSizeHint() const -{ - if (icon().isNull()) - { - return QSize(); - } - int icone = style()->pixelMetric(QStyle::PM_SmallIconSize); - return QSize(icone + 8, icone + 8); -} - -void QRollupCtrlButton::paintEvent(QPaintEvent*) -{ - QStylePainter p(this); - // draw the background manually, not to clash with UI 2.0 style shets - // the numbers here are taken from the stylesheet in the constructor - p.fillRect(QRect(5, 1, width() - 10, height() - 3), QColor(52, 52, 52)); - - { - QStyleOptionToolButton opt; - initStyleOption(&opt); - if (isSelected()) - { - if (opt.state & QStyle::State_MouseOver) - { - opt.state |= QStyle::State_Sunken; - } - opt.state |= QStyle::State_MouseOver; - } - p.drawComplexControl(QStyle::CC_ToolButton, opt); - } - - { - p.setPen(QPen(QColor(132, 128, 125))); - - int top = height() / 2 - 2; - p.drawLine(2, top, 4, top); - p.drawLine(width() - 5, top, width() - 3, top); - - int bottom = !isSelected() ? top + 4 : height(); - p.drawLine(2, bottom, 2, top); - p.drawLine(width() - 3, bottom, width() - 3, top); - - if (!isSelected()) - { - p.drawLine(2, bottom, 4, bottom); - p.drawLine(width() - 5, bottom, width() - 3, bottom); - } - } -} - -////////////////////////////////////////////////////////////////////////// - -QRollupCtrl::Page* QRollupCtrl::page(QWidget* widget) const -{ - if (!widget) - { - return 0; - } - - for (PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - if ((*i).widget == widget) - { - return (Page*)&(*i); - } - } - return 0; -} - -QRollupCtrl::Page* QRollupCtrl::page(int index) -{ - if (index >= 0 && index < m_pageList.size()) - { - return &m_pageList[index]; - } - return 0; -} - -const QRollupCtrl::Page* QRollupCtrl::page(int index) const -{ - if (index >= 0 && index < m_pageList.size()) - { - return &m_pageList.at(index); - } - return 0; -} - -inline void QRollupCtrl::Page::setText(const QString& text) { button->setText(text); } -inline void QRollupCtrl::Page::setIcon(const QIcon& is) { button->setIcon(is); } -inline void QRollupCtrl::Page::setToolTip(const QString& tip) { button->setToolTip(tip); } -inline QString QRollupCtrl::Page::text() const { return button->text(); } -inline QIcon QRollupCtrl::Page::icon() const { return button->icon(); } -inline QString QRollupCtrl::Page::toolTip() const { return button->toolTip(); } - -////////////////////////////////////////////////////////////////////////// - -QRollupCtrl::QRollupCtrl(QWidget* parent) - : QScrollArea(parent) - , m_layout(0) -{ - m_body = new QWidget(this); - m_body->setBackgroundRole(QPalette::Button); - setWidgetResizable(true); - setAlignment(Qt::AlignLeft | Qt::AlignTop); - setWidget(m_body); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - relayout(); -} - -QRollupCtrl::~QRollupCtrl() -{ - foreach(const QRollupCtrl::Page & c, m_pageList) - disconnect(c.widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); -} - -void QRollupCtrl::readSettings(const QString& qSettingsGroup) -{ - QSettings settings; - settings.beginGroup(qSettingsGroup); - - int i = 0; - foreach(const QRollupCtrl::Page & c, m_pageList) { - QString qObjectName = c.widget->objectName(); - - bool bHidden = settings.value(qObjectName, true).toBool(); - setIndexVisible(i++, !bHidden); - } - - settings.endGroup(); -} - -void QRollupCtrl::writeSettings(const QString& qSettingsGroup) -{ - QSettings settings; - settings.beginGroup(qSettingsGroup); - - for (int i = 0; i < count(); i++) - { - QString qObjectName; - bool bHidden = isPageHidden(i, qObjectName); - - settings.setValue(qObjectName, bHidden); - } -} - -void QRollupCtrl::updateTabs() -{ - for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - QRollupCtrlButton* tB = (*i).button; - QWidget* tW = (*i).sv; - tB->setSelected(tW->isVisible()); - tB->update(); - } -} - -int QRollupCtrl::insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text) -{ - if (!widget) - { - return -1; - } - - auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; }); - if (it != m_pageList.cend()) - { - return -1; - } - - connect(widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); - - QRollupCtrl::Page c; - c.widget = widget; - c.button = new QRollupCtrlButton(m_body); - c.button->setContextMenuPolicy(Qt::CustomContextMenu); - connect(c.button, &QRollupCtrlButton::clicked, this, &QRollupCtrl::_q_buttonClicked); - connect(c.button, &QRollupCtrlButton::customContextMenuRequested, this, &QRollupCtrl::_q_custumButtonMenu); - - c.sv = new QFrame(m_body); - c.sv->setObjectName("rollupPaneFrame"); - // c.sv->setFixedHeight(qMax(widget->sizeHint().height(), widget->size().height())); - QVBoxLayout* layout = new QVBoxLayout; - layout->setMargin(3); - layout->addWidget(widget); - c.sv->setLayout(layout); - c.sv->setStyleSheet("QFrame#rollupPaneFrame {margin: 0px 2px 2px 2px; border: 1px solid #84807D; border-top:0px;}"); - c.sv->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - c.sv->show(); - - c.setText(text); - c.setIcon(icon); - - const int numPages = m_pageList.count(); - if (index < 0 || index >= numPages) - { - m_pageList.append(c); - index = numPages - 1; - m_layout->insertWidget(m_layout->count() - 1, c.button); - m_layout->insertWidget(m_layout->count() - 1, c.sv); - } - else - { - m_pageList.insert(index, c); - relayout(); - } - - c.button->show(); - - updateTabs(); - itemInserted(index); - return index; -} - -void QRollupCtrl::_q_buttonClicked() -{ - QObject* tb = sender(); - QWidget* item = 0; - for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - if ((*i).button == tb) - { - item = (*i).widget; - break; - } - } - - if (item) - { - setIndexVisible(indexOf(item), !item->isVisible()); - } -} - -int QRollupCtrl::count() const -{ - return m_pageList.count(); -} - -bool QRollupCtrl::isPageHidden(int index, QString& qObjectName) const -{ - if (index < 0 || index >= m_pageList.size()) - { - return true; - } - const QRollupCtrl::Page& c = m_pageList.at(index); - qObjectName = c.widget->objectName(); - return c.sv->isHidden(); -} - -void QRollupCtrl::setIndexVisible(int index, bool visible) -{ - QRollupCtrl::Page* c = page(index); - if (!c) - { - return; - } - - if (c->sv->isHidden() && visible) - { - c->sv->show(); - } - else if (c->sv->isVisible() && !visible) - { - c->sv->hide(); - } - updateTabs(); -} - -void QRollupCtrl::setWidgetVisible(QWidget* widget, bool visible) -{ - setIndexVisible(indexOf(widget), visible); -} - -void QRollupCtrl::relayout() -{ - delete m_layout; - m_layout = new QVBoxLayout(m_body); - m_layout->setMargin(3); - m_layout->setSpacing(0); - for (QRollupCtrl::PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - m_layout->addWidget((*i).button); - m_layout->addWidget((*i).sv); - } - m_layout->addStretch(); - updateTabs(); -} - -void QRollupCtrl::_q_widgetDestroyed(QObject* object) -{ - // no verification - vtbl corrupted already - QWidget* p = (QWidget*)object; - - QRollupCtrl::Page* c = page(p); - if (!p || !c) - { - return; - } - - m_layout->removeWidget(c->sv); - m_layout->removeWidget(c->button); - c->sv->deleteLater(); // page might still be a child of sv - delete c->button; - - m_pageList.removeOne(*c); -} - -void QRollupCtrl::_q_custumButtonMenu([[maybe_unused]] const QPoint& pos) -{ - QMenu menu; - menu.addAction("Expand All")->setData(-1); - menu.addAction("Collapse All")->setData(-2); - menu.addSeparator(); - for (int i = 0; i < m_pageList.size(); ++i) - { - QRollupCtrl::Page* c = page(i); - QAction* action = menu.addAction(c->button->text()); - action->setCheckable(true); - action->setChecked(c->sv->isVisible()); - action->setData(i); - } - - QAction* action = menu.exec(QCursor::pos()); - if (!action) - { - return; - } - int res = action->data().toInt(); - switch (res) - { - case -1: // fall through - case -2: - expandAllPages(res == -1); - break; - default: - { - QRollupCtrl::Page* c = page(res); - if (c) - { - setIndexVisible(res, !c->sv->isVisible()); - } - } - break; - } -} - -void QRollupCtrl::expandAllPages(bool v) -{ - for (int i = 0; i < m_pageList.size(); i++) - { - setIndexVisible(i, v); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void QRollupCtrl::clear() -{ - while (!m_pageList.isEmpty()) - { - removeItem(0); - } -} - -void QRollupCtrl::removeItem(QWidget* widget) -{ - auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; }); - if (it != m_pageList.cend()) - { - removeItem(it - m_pageList.cbegin()); - } -} - -void QRollupCtrl::removeItem(int index) -{ - if (QWidget* w = widget(index)) - { - disconnect(w, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); - w->setParent(this); - // destroy internal data - _q_widgetDestroyed(w); - itemRemoved(index); - } -} - -QWidget* QRollupCtrl::widget(int index) const -{ - if (index < 0 || index >= (int) m_pageList.size()) - { - return 0; - } - return m_pageList.at(index).widget; -} - -int QRollupCtrl::indexOf(QWidget* widget) const -{ - QRollupCtrl::Page* c = page(widget); - return c ? m_pageList.indexOf(*c) : -1; -} - -void QRollupCtrl::setItemEnabled(int index, bool enabled) -{ - QRollupCtrl::Page* c = page(index); - if (!c) - { - return; - } - - c->button->setEnabled(enabled); - if (!enabled) - { - int curIndexUp = index; - int curIndexDown = curIndexUp; - const int count = m_pageList.count(); - while (curIndexUp > 0 || curIndexDown < count - 1) - { - if (curIndexDown < count - 1) - { - if (page(++curIndexDown)->button->isEnabled()) - { - index = curIndexDown; - break; - } - } - if (curIndexUp > 0) - { - if (page(--curIndexUp)->button->isEnabled()) - { - index = curIndexUp; - break; - } - } - } - } -} - -void QRollupCtrl::setItemText(int index, const QString& text) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setText(text); - } -} - -void QRollupCtrl::setItemIcon(int index, const QIcon& icon) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setIcon(icon); - } -} - -void QRollupCtrl::setItemToolTip(int index, const QString& toolTip) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setToolTip(toolTip); - } -} - -bool QRollupCtrl::isItemEnabled(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return c && c->button->isEnabled(); -} - -QString QRollupCtrl::itemText(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->text() : QString()); -} - -QIcon QRollupCtrl::itemIcon(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->icon() : QIcon()); -} - -QString QRollupCtrl::itemToolTip(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->toolTip() : QString()); -} - -void QRollupCtrl::changeEvent(QEvent* ev) -{ - if (ev->type() == QEvent::StyleChange) - { - updateTabs(); - } - QFrame::changeEvent(ev); -} - -void QRollupCtrl::showEvent(QShowEvent* ev) -{ - if (isVisible()) - { - updateTabs(); - } - IEditor* pEditor = GetIEditor(); - pEditor->SetEditMode(EEditMode::eEditModeSelect); - QFrame::showEvent(ev); -} - -void QRollupCtrl::itemInserted(int index) -{ - Q_UNUSED(index) -} - -void QRollupCtrl::itemRemoved(int index) -{ - Q_UNUSED(index) -} - - -#include diff --git a/Code/Sandbox/Editor/Controls/QRollupCtrl.h b/Code/Sandbox/Editor/Controls/QRollupCtrl.h deleted file mode 100644 index 3db8bdf860..0000000000 --- a/Code/Sandbox/Editor/Controls/QRollupCtrl.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H - -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#endif - -class QVBoxLayout; -class QRollupCtrlButton; - -class QRollupCtrl - : public QScrollArea -{ - Q_OBJECT - Q_PROPERTY(int count READ count) - -public: - explicit QRollupCtrl(QWidget* parent = 0); - ~QRollupCtrl(); - - int addItem(QWidget* widget, const QString& text); - int addItem(QWidget* widget, const QIcon& icon, const QString& text); - int insertItem(int index, QWidget* widget, const QString& text); - int insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text); - - void clear(); - void removeItem(QWidget* widget); - void removeItem(int index); - - void setItemEnabled(int index, bool enabled); - bool isItemEnabled(int index) const; - - void setItemText(int index, const QString& text); - QString itemText(int index) const; - - void setItemIcon(int index, const QIcon& icon); - QIcon itemIcon(int index) const; - - void setItemToolTip(int index, const QString& toolTip); - QString itemToolTip(int index) const; - - QWidget* widget(int index) const; - int indexOf(QWidget* widget) const; - int count() const; - - void readSettings (const QString& qSettingsGroup); - void writeSettings(const QString& qSettingsGroup); - -public slots: - void setIndexVisible(int index, bool visible); - void setWidgetVisible(QWidget* widget, bool visible); - void expandAllPages(bool v); - -protected: - virtual void itemInserted(int index); - virtual void itemRemoved(int index); - void changeEvent(QEvent*) override; - void showEvent(QShowEvent*) override; - -private: - Q_DISABLE_COPY(QRollupCtrl) - - struct Page - { - QRollupCtrlButton* button; - QFrame* sv; - QWidget* widget; - - void setText(const QString& text); - void setIcon(const QIcon& is); - void setToolTip(const QString& tip); - QString text() const; - QIcon icon() const; - QString toolTip() const; - - inline bool operator==(const Page& other) const - { - return widget == other.widget; - } - }; - typedef QList PageList; - - Page* page(QWidget* widget) const; - const Page* page(int index) const; - Page* page(int index); - - void updateTabs(); - void relayout(); - bool isPageHidden(int index, QString& qObjectName) const; - - QWidget* m_body; - PageList m_pageList; - QVBoxLayout* m_layout; - -private slots: - void _q_buttonClicked(); - void _q_widgetDestroyed(QObject*); - void _q_custumButtonMenu(const QPoint&); -}; - - -////////////////////////////////////////////////////////////////////////// - -inline int QRollupCtrl::addItem(QWidget* item, const QString& text) -{ return insertItem(-1, item, QIcon(), text); } -inline int QRollupCtrl::addItem(QWidget* item, const QIcon& iconSet, const QString& text) -{ return insertItem(-1, item, iconSet, text); } -inline int QRollupCtrl::insertItem(int index, QWidget* item, const QString& text) -{ return insertItem(index, item, QIcon(), text); } - -#endif diff --git a/Code/Sandbox/Editor/Controls/ToolButton.cpp b/Code/Sandbox/Editor/Controls/ToolButton.cpp deleted file mode 100644 index b74fe1a330..0000000000 --- a/Code/Sandbox/Editor/Controls/ToolButton.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : implementation file - - -#include "EditorDefs.h" - -// Editor -#include "CryEditDoc.h" -#include "EditTool.h" -#include "ToolButton.h" - - -QEditorToolButton::QEditorToolButton(QWidget* parent /* = nullptr */) - : QPushButton(parent) - , m_styleSheet(styleSheet()) - , m_toolClass(nullptr) - , m_toolCreated(nullptr) - , m_needDocument(true) -{ - setSizePolicy({ QSizePolicy::Expanding, QSizePolicy::Fixed }); - connect(this, &QAbstractButton::clicked, this, &QEditorToolButton::OnClicked); - GetIEditor()->RegisterNotifyListener(this); -} - -QEditorToolButton::~QEditorToolButton() -{ - GetIEditor()->UnregisterNotifyListener(this); -} - -void QEditorToolButton::SetToolName(const QString& editToolName, const QString& userDataKey, void* userData) -{ - IClassDesc* klass = GetIEditor()->GetClassFactory()->FindClass(editToolName.toUtf8().data()); - if (!klass) - { - Warning(QStringLiteral("Editor Tool %1 not registered.").arg(editToolName).toUtf8().data()); - return; - } - if (klass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL) - { - Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data()); - return; - } - - QScopedPointer o(klass->CreateQObject()); - if (!qobject_cast(o.data())) - { - Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data()); - return; - } - SetToolClass(o->metaObject(), userDataKey, userData); -} - -////////////////////////////////////////////////////////////////////////// -void QEditorToolButton::SetToolClass(const QMetaObject* toolClass, const QString& userDataKey, void* userData) -{ - m_toolClass = toolClass; - - m_userData = userData; - if (!userDataKey.isEmpty()) - { - m_userDataKey = userDataKey; - } -} - -void QEditorToolButton::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginNewScene: - case eNotify_OnBeginLoad: - case eNotify_OnBeginSceneOpen: - { - if (m_needDocument) - { - setEnabled(false); - } - break; - } - - case eNotify_OnEndNewScene: - case eNotify_OnEndLoad: - case eNotify_OnEndSceneOpen: - { - if (m_needDocument) - { - setEnabled(true); - } - break; - } - case eNotify_OnEditToolChange: - { - CEditTool* tool = GetIEditor()->GetEditTool(); - - if (!tool || tool != m_toolCreated || tool->metaObject() != m_toolClass) - { - m_toolCreated = nullptr; - SetSelected(false); - } - } - default: - break; - } -} - -void QEditorToolButton::OnClicked() -{ - if (!m_toolClass) - { - return; - } - - if (m_needDocument && !GetIEditor()->GetDocument()->IsDocumentReady()) - { - return; - } - - CEditTool* tool = GetIEditor()->GetEditTool(); - if (tool && tool->IsMoveToObjectModeAfterEnd() && tool->metaObject() == m_toolClass && tool == m_toolCreated) - { - GetIEditor()->SetEditTool(nullptr); - SetSelected(false); - } - else - { - CEditTool* newTool = qobject_cast(m_toolClass->newInstance()); - if (!newTool) - { - return; - } - - m_toolCreated = newTool; - - SetSelected(true); - - if (m_userData) - { - newTool->SetUserData(m_userDataKey.toUtf8().data(), (void*)m_userData); - } - - update(); - - // Must be last function, can delete this. - GetIEditor()->SetEditTool(newTool); - } -} - -void QEditorToolButton::SetSelected(bool selected) -{ - if (selected) - { - setStyleSheet(QStringLiteral("QPushButton { background-color: palette(highlight); color: palette(highlighted-text); }")); - } - else - { - setStyleSheet(m_styleSheet); - } -} - -#include diff --git a/Code/Sandbox/Editor/Controls/ToolButton.h b/Code/Sandbox/Editor/Controls/ToolButton.h deleted file mode 100644 index f32bd6678d..0000000000 --- a/Code/Sandbox/Editor/Controls/ToolButton.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H -#define CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H -#pragma once - -// ToolButton.h : header file -// - -#if !defined(Q_MOC_RUN) -#include -#include -#endif - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -class SANDBOX_API QEditorToolButton - : public QPushButton - , public IEditorNotifyListener -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING - Q_OBJECT - // Construction -public: - QEditorToolButton(QWidget* parent = nullptr); - virtual ~QEditorToolButton(); - - void SetToolClass(const QMetaObject* toolClass, const QString& userDataKey = 0, void* userData = nullptr); - void SetToolName(const QString& editToolName, const QString& userDataKey = 0, void* userData = nullptr); - // Set if this tool button relies on a loaded level / ready document. By default every tool button only works if a level is loaded. - // However some tools are also used without a loaded level (e.g. UI Emulator) - void SetNeedDocument(bool needDocument) { m_needDocument = needDocument; } - - void SetSelected(bool selected); - void OnEditorNotifyEvent(EEditorNotifyEvent event) override; -protected: - void OnClicked(); - - const QString m_styleSheet; - - //! Tool associated with this button. - const QMetaObject* m_toolClass; - CEditTool* m_toolCreated; - QString m_userDataKey; - void* m_userData; - bool m_needDocument; -}; - - -#endif // CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index f00085d5ad..0863e1627f 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -580,7 +580,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe auto alignMenu = modifyMenu.AddMenu(tr("Align")); alignMenu.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID); - alignMenu.AddAction(ID_MODIFY_ALIGNOBJTOSURF); auto constrainMenu = modifyMenu.AddMenu(tr("Constrain")); constrainMenu.AddAction(ID_SELECT_AXIS_X); diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 7aefcffb5a..b373ef0009 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -95,7 +95,6 @@ AZ_POP_DISABLE_WARNING #include "Core/QtEditorApplication.h" #include "StringDlg.h" -#include "VoxelAligningTool.h" #include "NewLevelDialog.h" #include "GridSettingsDialog.h" #include "LayoutConfigDialog.h" @@ -110,7 +109,6 @@ AZ_POP_DISABLE_WARNING #include "DisplaySettings.h" #include "GameEngine.h" -#include "ObjectCloneTool.h" #include "StartupTraceHandler.h" #include "ThumbnailGenerator.h" #include "ToolsConfigPage.h" @@ -153,7 +151,6 @@ AZ_POP_DISABLE_WARNING #include "LevelIndependentFileMan.h" #include "WelcomeScreen/WelcomeScreenDialog.h" #include "Dialogs/DuplicatedObjectsHandlerDlg.h" -#include "EditMode/VertexSnappingModeTool.h" #include "Controls/ReflectedPropertyControl/PropertyCtrl.h" #include "Controls/ReflectedPropertyControl/ReflectedVar.h" @@ -399,11 +396,8 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDITMODE_ROTATE, OnEditmodeRotate) ON_COMMAND(ID_EDITMODE_SCALE, OnEditmodeScale) ON_COMMAND(ID_EDITMODE_SELECT, OnEditmodeSelect) - ON_COMMAND(ID_EDIT_ESCAPE, OnEditEscape) ON_COMMAND(ID_OBJECTMODIFY_SETAREA, OnObjectSetArea) ON_COMMAND(ID_OBJECTMODIFY_SETHEIGHT, OnObjectSetHeight) - ON_COMMAND(ID_OBJECTMODIFY_VERTEXSNAPPING, OnObjectVertexSnapping) - ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel) ON_COMMAND(ID_OBJECTMODIFY_FREEZE, OnObjectmodifyFreeze) ON_COMMAND(ID_OBJECTMODIFY_UNFREEZE, OnObjectmodifyUnfreeze) ON_COMMAND(ID_EDITMODE_SELECTAREA, OnEditmodeSelectarea) @@ -413,11 +407,9 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_SELECT_AXIS_XY, OnSelectAxisXy) ON_COMMAND(ID_UNDO, OnUndo) ON_COMMAND(ID_TOOLBAR_WIDGET_REDO, OnUndo) // Can't use the same ID, because for the menu we can't have a QWidgetAction, while for the toolbar we want one - ON_COMMAND(ID_EDIT_CLONE, OnEditClone) ON_COMMAND(ID_SELECTION_SAVE, OnSelectionSave) ON_COMMAND(ID_IMPORT_ASSET, OnOpenAssetImporter) ON_COMMAND(ID_SELECTION_LOAD, OnSelectionLoad) - ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel) ON_COMMAND(ID_OBJECTMODIFY_ALIGNTOGRID, OnAlignToGrid) ON_COMMAND(ID_LOCK_SELECTION, OnLockSelection) ON_COMMAND(ID_EDIT_LEVELDATA, OnEditLevelData) @@ -524,12 +516,10 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_OPEN_MATERIAL_EDITOR, OnOpenMaterialEditor) ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch) - ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool) ON_COMMAND(ID_DISPLAY_SHOWHELPERS, OnShowHelpers) ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView) ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor) ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch) - ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool) ON_COMMAND(ID_TERRAIN_TIMEOFDAY, OnTimeOfDay) ON_COMMAND(ID_TERRAIN_TIMEOFDAYBUTTON, OnTimeOfDay) @@ -2739,15 +2729,6 @@ void CCryEditApp::OnEditDelete() ////////////////////////////////////////////////////////////////////////// void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendants) { - // If Edit tool active cannot delete object. - if (GetIEditor()->GetEditTool()) - { - if (GetIEditor()->GetEditTool()->OnKeyDown(GetIEditor()->GetViewManager()->GetView(0), VK_DELETE, 0, 0)) - { - return; - } - } - GetIEditor()->BeginUndo(); CUndo undo("Delete Selected Object"); GetIEditor()->GetObjectManager()->DeleteSelection(); @@ -2756,75 +2737,6 @@ void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendant GetIEditor()->SetModifiedModule(eModifiedBrushes); } -void CCryEditApp::OnEditClone() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - if (GetIEditor()->GetObjectManager()->GetSelection()->IsEmpty()) - { - QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), - QObject::tr("You have to select objects before you can clone them!")); - return; - } - - // Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor is being edited. - if (QApplication::focusWidget()) - { - QApplication::focusWidget()->clearFocus(); - } - - CEditTool* tool = GetIEditor()->GetEditTool(); - if (tool && qobject_cast(tool)) - { - ((CObjectCloneTool*)tool)->Accept(); - } - - CObjectCloneTool* cloneTool = new CObjectCloneTool; - GetIEditor()->SetEditTool(cloneTool); - GetIEditor()->SetModifiedFlag(); - GetIEditor()->SetModifiedModule(eModifiedBrushes); - - // Accept the clone operation if users didn't choose to stick duplicated entities to the cursor - // This setting can be changed in the global preference of the editor - if (!gSettings.deepSelectionSettings.bStickDuplicate) - { - cloneTool->Accept(); - GetIEditor()->GetSelection()->FinishChanges(); - } - } -} - -void CCryEditApp::OnEditEscape() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - // Abort current operation. - if (pEditTool) - { - // If Edit tool active cannot delete object. - CViewport* vp = GetIEditor()->GetActiveView(); - if (GetIEditor()->GetEditTool()->OnKeyDown(vp, VK_ESCAPE, 0, 0)) - { - return; - } - - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - GetIEditor()->SetEditMode(eEditModeSelect); - } - - // Disable current tool. - GetIEditor()->SetEditTool(0); - } - else - { - // Clear selection on escape. - GetIEditor()->ClearSelection(); - } - } -} - void CCryEditApp::OnMoveObject() { //////////////////////////////////////////////////////////////////////// @@ -2986,14 +2898,6 @@ void CCryEditApp::OnUpdateEditmodeScale(QAction* action) } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateEditmodeVertexSnapping(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - action->setChecked(qobject_cast(pEditTool) != nullptr); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnObjectSetArea() { @@ -3143,19 +3047,6 @@ void CCryEditApp::OnObjectSetHeight() } } -void CCryEditApp::OnObjectVertexSnapping() -{ - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (qobject_cast(pEditTool)) - { - GetIEditor()->SetEditTool(NULL); - } - else - { - GetIEditor()->SetEditTool("EditTool.VertexSnappingMode"); - } -} - void CCryEditApp::OnObjectmodifyFreeze() { // Freeze selection. @@ -3480,37 +3371,8 @@ void CCryEditApp::OnAlignToGrid() } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnAlignToVoxel() -{ - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (qobject_cast(pEditTool) != nullptr) - { - GetIEditor()->SetEditTool(nullptr); - } - else - { - GetIEditor()->SetEditTool(new CVoxelAligningTool()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateAlignToVoxel(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - action->setChecked(qobject_cast(pEditTool) != nullptr); - - action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty()); -} - void CCryEditApp::OnShowHelpers() { - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - return; - } GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()); GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate); } @@ -5136,12 +4998,6 @@ void CCryEditApp::OnOpenUICanvasEditor() QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnMaterialPicktool() -{ - GetIEditor()->SetEditTool("EditTool.PickMaterial"); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnTimeOfDay() { @@ -5296,12 +5152,6 @@ void CCryEditApp::OnOpenQuickAccessBar() return; } - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - return; - } - QRect geo = m_pQuickAccessBar->geometry(); geo.moveCenter(MainWindow::instance()->geometry().center()); m_pQuickAccessBar->setGeometry(geo); diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 94c39991e9..7c77a03bb4 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -225,11 +225,8 @@ public: void OnEditmodeRotate(); void OnEditmodeScale(); void OnEditmodeSelect(); - void OnEditEscape(); void OnObjectSetArea(); void OnObjectSetHeight(); - void OnObjectVertexSnapping(); - void OnUpdateEditmodeVertexSnapping(QAction* action); void OnUpdateEditmodeSelect(QAction* action); void OnUpdateEditmodeMove(QAction* action); void OnUpdateEditmodeRotate(QAction* action); @@ -247,14 +244,11 @@ public: void OnUpdateSelectAxisY(QAction* action); void OnUpdateSelectAxisZ(QAction* action); void OnUndo(); - void OnEditClone(); void OnSelectionSave(); void OnOpenAssetImporter(); void OnSelectionLoad(); void OnUpdateSelected(QAction* action); - void OnAlignToVoxel(); void OnAlignToGrid(); - void OnUpdateAlignToVoxel(QAction* action); void OnLockSelection(); void OnEditLevelData(); void OnFileEditLogFile(); @@ -491,7 +485,6 @@ private: void OnOpenAudioControlsEditor(); void OnOpenUICanvasEditor(); void OnGotoViewportSearch(); - void OnMaterialPicktool(); void OnTimeOfDay(); void OnChangeGameSpec(UINT nID); void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 15269c1496..a94d588516 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -279,7 +279,6 @@ void CCryEditDoc::DeleteContents() // [LY-90904] move this to the EditorVegetationManager component InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData); - GetIEditor()->SetEditTool(0); // Turn off any active edit tools. GetIEditor()->SetEditMode(eEditModeSelect); ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp b/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp deleted file mode 100644 index 8314361585..0000000000 --- a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "ButtonsPanel.h" - -// Qt -#include - -// Editor -#include "Controls/ToolButton.h" - -///////////////////////////////////////////////////////////////////////////// -// CButtonsPanel dialog -CButtonsPanel::CButtonsPanel(QWidget* parent) - : QWidget(parent) -{ -} - -CButtonsPanel::~CButtonsPanel() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const SButtonInfo& button) -{ - SButton b; - b.info = button; - m_buttons.push_back(b); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const QString& name, const QString& toolClass) -{ - SButtonInfo bi; - bi.name = name; - bi.toolClassName = toolClass; - AddButton(bi); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const QString& name, const QMetaObject* pToolClass) -{ - SButtonInfo bi; - bi.name = name; - bi.pToolClass = pToolClass; - AddButton(bi); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::ClearButtons() -{ - auto buttons = layout()->findChildren(); - foreach(auto button, buttons) - { - layout()->removeWidget(button); - delete button; - } - m_buttons.clear(); -} - -void CButtonsPanel::UncheckAll() -{ - for (auto& button : m_buttons) - { - button.pButton->SetSelected(false); - } -} - -void CButtonsPanel::OnInitDialog() -{ - auto layout = new QGridLayout(this); - setLayout(layout); - - layout->setMargin(4); - layout->setHorizontalSpacing(4); - layout->setVerticalSpacing(1); - - // Create Buttons. - int index = 0; - for (auto& button : m_buttons) - { - button.pButton = new QEditorToolButton(this); - button.pButton->setObjectName(button.info.name); - button.pButton->setText(button.info.name); - button.pButton->SetNeedDocument(button.info.bNeedDocument); - button.pButton->setToolTip(button.info.toolTip); - - if (button.info.pToolClass) - { - button.pButton->SetToolClass(button.info.pToolClass, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str()); - } - else if (!button.info.toolClassName.isEmpty()) - { - button.pButton->SetToolName(button.info.toolClassName, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str()); - } - - layout->addWidget(button.pButton, index / 2, index % 2); - connect(button.pButton, &QEditorToolButton::clicked, this, [&]() { OnButtonPressed(button.info); }); - ++index; - } -} - -void CButtonsPanel::EnableButton(const QString& buttonName, bool enable) -{ - for (auto& button : m_buttons) - { - if (button.pButton->objectName() == buttonName) - { - button.pButton->setEnabled(enable); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h b/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h deleted file mode 100644 index c214c7625b..0000000000 --- a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H -#define CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#endif - -class QEditorToolButton; - -///////////////////////////////////////////////////////////////////////////// -// Panel with custom auto arranged buttons -class CButtonsPanel - : public QWidget -{ - Q_OBJECT -public: - - struct SButtonInfo - { - QString name; - QString toolClassName; - QString toolUserDataKey; - std::string toolUserData; - QString toolTip; - bool bNeedDocument; - const QMetaObject* pToolClass; - - SButtonInfo() - : pToolClass(nullptr) - , bNeedDocument(true) {}; - }; - - CButtonsPanel(QWidget* parent); - virtual ~CButtonsPanel(); - - virtual void AddButton(const SButtonInfo& button); - virtual void AddButton(const QString& name, const QString& toolClass); - virtual void AddButton(const QString& name, const QMetaObject* pToolClass); - virtual void EnableButton(const QString& buttonName, bool disable); - virtual void ClearButtons(); - - virtual void OnButtonPressed([[maybe_unused]] const SButtonInfo& button) {}; - virtual void UncheckAll(); - -protected: - void ReleaseGuiButtons(); - - virtual void OnInitDialog(); - - ////////////////////////////////////////////////////////////////////////// - struct SButton - { - SButtonInfo info; - QEditorToolButton* pButton; - SButton() - : pButton(nullptr) {}; - }; - - std::vector m_buttons; -}; - -#endif // CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H diff --git a/Code/Sandbox/Editor/EditMode/ObjectMode.cpp b/Code/Sandbox/Editor/EditMode/ObjectMode.cpp deleted file mode 100644 index 3454cfefd3..0000000000 --- a/Code/Sandbox/Editor/EditMode/ObjectMode.cpp +++ /dev/null @@ -1,1525 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#if defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include "ObjectMode.h" - -// Qt -#include - -// AzToolsFramework -#include -#include -#include - -// Editor -#include "Viewport.h" -#include "ViewManager.h" -#include "Settings.h" -#include "Objects/SelectionGroup.h" - -#include "GameEngine.h" -#include "Objects/DisplayContext.h" -#include "Objects/EntityObject.h" -#include "AnimationContext.h" -#include "DeepSelection.h" -#include "SubObjectSelectionReferenceFrameCalculator.h" -#include "ITransformManipulator.h" -#include "SurfaceInfoPicker.h" -#include "RenderViewport.h" -#include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" - - -////////////////////////////////////////////////////////////////////////// -CObjectMode::CObjectMode(QObject* parent) - : CEditTool(parent) -{ - m_pClassDesc = GetIEditor()->GetClassFactory()->FindClass(OBJECT_MODE_GUID); - SetStatusText(tr("Object Selection")); - - m_openContext = false; - m_commandMode = NothingMode; - m_MouseOverObject = GuidUtil::NullGuid; - - m_pDeepSelection = new CDeepSelection(); - m_bMoveByFaceNormManipShown = false; - m_pHitObject = NULL; - - m_bTransformChanged = false; -} - -////////////////////////////////////////////////////////////////////////// -CObjectMode::~CObjectMode() -{ -} - -void CObjectMode::DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject) -{ - AABB bbox; - drawObject->GetBoundBox(bbox); - - AZStd::string cleanName = drawObject->GetName().toUtf8().data(); - - // Since we'll be passing this in as a format for a sprintf, need to cleanup any %'s so they display correctly - size_t index = cleanName.find("%", 0); - while (index != std::string::npos) - { - cleanName.insert(index, "%", 1); - - // Increment index past the replacement so it doesn't get picked up again on the next loop - index = cleanName.find("%", index + 2); - } - - // If CGroup/CPrefabObject - if (drawObject->GetChildCount() > 0) - { - // Draw object name label on top of object - Vec3 vTopEdgeCenterPos = bbox.GetCenter(); - - dc.SetColor(gSettings.objectColorSettings.groupHighlight); - vTopEdgeCenterPos(vTopEdgeCenterPos.x, vTopEdgeCenterPos.y, bbox.max.z); - dc.DrawTextLabel(vTopEdgeCenterPos, 1.3f, cleanName.c_str()); - // Draw bounding box wireframe - dc.DrawWireBox(bbox.min, bbox.max); - } - else - { - dc.SetColor(Vec3(1, 1, 1)); - dc.DrawTextLabel(bbox.GetCenter(), 1.5, cleanName.c_str()); - } - - // Object Geometry Highlight - - const float normalizedFloatToUint8 = 255.0f; - - // Default object - ColorB selColor = ColorB(gSettings.objectColorSettings.geometryHighlightColor.red(), gSettings.objectColorSettings.geometryHighlightColor.green(), gSettings.objectColorSettings.geometryHighlightColor.blue(), gSettings.objectColorSettings.fGeomAlpha * normalizedFloatToUint8); - - // In case it is a child object, use a different alpha value - if (drawObject->GetParent()) - { - selColor.a = (uint8)(gSettings.objectColorSettings.fChildGeomAlpha * normalizedFloatToUint8); - } - - // Draw geometry in custom color - SGeometryDebugDrawInfo dd; - dd.tm = drawObject->GetWorldTM(); - dd.color = selColor; - dd.lineColor = selColor; - dd.bExtrude = true; - - if (qobject_cast(drawObject)) - { - dc.DepthTestOff(); - dc.SetColor(gSettings.objectColorSettings.entityHighlight, gSettings.objectColorSettings.fBBoxAlpha * normalizedFloatToUint8); - dc.DrawSolidBox(bbox.min, bbox.max); - dc.DepthTestOn(); - - CEntityObject* entityObj = (CEntityObject*)drawObject; - if (entityObj) - { - entityObj->DrawExtraLightInfo(dc); - } - } - - // Highlight also children objects if this object is opened - for (int gNo = 0; gNo < drawObject->GetChildCount(); ++gNo) - { - if (std::find(m_PreviewGUIDs.begin(), m_PreviewGUIDs.end(), drawObject->GetChild(gNo)->GetId()) == m_PreviewGUIDs.end()) - { - DrawSelectionPreview(dc, drawObject->GetChild(gNo)); - } - } -} - -void CObjectMode::DisplaySelectionPreview(struct DisplayContext& dc) -{ - CViewport* view = dc.view->asCViewport(); - IObjectManager* objMan = GetIEditor()->GetObjectManager(); - - if (!view) - { - return; - } - - QRect rc = view->GetSelectionRectangle(); - - if (GetCommandMode() == SelectMode) - { - if (rc.width() > 1 && rc.height() > 1) - { - GetIEditor()->GetObjectManager()->FindObjectsInRect(view, rc, m_PreviewGUIDs); - - QString selCountStr; - - // Do not include child objects in the count of object candidates - int childNo = 0; - for (int objNo = 0; objNo < m_PreviewGUIDs.size(); ++objNo) - { - if (objMan->FindObject(m_PreviewGUIDs[objNo])) - { - if (objMan->FindObject(m_PreviewGUIDs[objNo])->GetParent()) - { - ++childNo; - } - } - } - - selCountStr = QString::number(m_PreviewGUIDs.size() - childNo); - GetIEditor()->SetStatusText(tr("Selection Candidates Count: %1").arg(selCountStr)); - - // Draw Preview for objects - for (size_t i = 0; i < m_PreviewGUIDs.size(); ++i) - { - CBaseObject* curObj = GetIEditor()->GetObjectManager()->FindObject(m_PreviewGUIDs[i]); - - if (!curObj) - { - continue; - } - - DrawSelectionPreview(dc, curObj); - } - } - } -} - -void CObjectMode::DisplayExtraLightInfo(struct DisplayContext& dc) -{ - if (m_MouseOverObject != GUID_NULL) - { - IObjectManager* objMan = GetIEditor()->GetObjectManager(); - - if (objMan) - { - CBaseObject* hitObj = objMan->FindObject(m_MouseOverObject); - - if (hitObj) - { - if (objMan->IsLightClass(hitObj)) - { - CEntityObject* entityObj = (CEntityObject*)hitObj; - if (entityObj) - { - entityObj->DrawExtraLightInfo(dc); - } - } - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::EndEditParams() -{ - CBaseObject* pMouseOverObject = nullptr; - if (!GuidUtil::IsEmpty(m_MouseOverObject)) - { - pMouseOverObject = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject); - } - - if (pMouseOverObject) - { - pMouseOverObject->SetHighlight(false); - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::Display(struct DisplayContext& dc) -{ - // Selection Candidates Preview - DisplaySelectionPreview(dc); - DisplayExtraLightInfo(dc); - - GetIEditor()->GetSelection()->IndicateSnappingVertex(dc); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - switch (event) - { - case eMouseLDown: - return OnLButtonDown(view, flags, point); - break; - case eMouseLUp: - return OnLButtonUp(view, flags, point); - break; - case eMouseLDblClick: - return OnLButtonDblClk(view, flags, point); - break; - case eMouseRDown: - return OnRButtonDown(view, flags, point); - break; - case eMouseRUp: - return OnRButtonUp(view, flags, point); - break; - case eMouseMove: - return OnMouseMove(view, flags, point); - break; - case eMouseMDown: - return OnMButtonDown(view, flags, point); - break; - case eMouseLeave: - return OnMouseLeave(view); - break; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->ClearSelection(); - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonDown(CViewport* view, int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (m_bMoveByFaceNormManipShown) - { - HideMoveByFaceNormGizmo(); - } - - // CPointF ptMarker; - QPoint ptCoord; - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore clicks while in game. - return false; - } - - // Allow interception of mouse clicks for custom behavior. - bool handledExternally = false; - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, - HandleObjectModeSelection, - AZ::Vector2(static_cast(point.x()), static_cast(point.y())), - nFlags, - handledExternally); - if (handledExternally) - { - return true; - } - - // Save the mouse down position - m_cMouseDownPos = point; - m_bDragThresholdExceeded = false; - - view->ResetSelectionRegion(); - - Vec3 pos = view->SnapToGrid(view->ViewToWorld(point)); - - // Swap X/Y - int unitSize = 1; - float hx = pos.y / unitSize; - float hy = pos.x / unitSize; - float hz = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - - char szNewStatusText[512]; - sprintf_s(szNewStatusText, "Heightmap Coordinates: HX:%g HY:%g HZ:%g", hx, hy, hz); - GetIEditor()->SetStatusText(szNewStatusText); - - // Get control key status. - const bool bAltClick = (Qt::AltModifier & QApplication::queryKeyboardModifiers()); - bool bCtrlClick = (nFlags & MK_CONTROL); - bool bShiftClick = (nFlags & MK_SHIFT); - - bool bAddSelect = bCtrlClick; - bool bUnselect = bAltClick; - bool bNoRemoveSelection = bAddSelect || bUnselect; - - // Check deep selection mode activated - // The Deep selection has two mode. - // The normal mode pops the context menu, another is the cyclic selection on clinking. - const bool bTabPressed = CheckVirtualKey(Qt::Key_Tab); - const bool bZKeyPressed = CheckVirtualKey(Qt::Key_Z); - - CDeepSelection::EDeepSelectionMode dsMode = - (bTabPressed ? (bZKeyPressed ? CDeepSelection::DSM_POP : CDeepSelection::DSM_CYCLE) : CDeepSelection::DSM_NONE); - - bool bLockSelection = GetIEditor()->IsSelectionLocked(); - - int numUnselected = 0; - int numSelected = 0; - - // m_activeAxis = 0; - - HitContext hitInfo; - hitInfo.view = view; - if (bAddSelect || bUnselect) - { - // If adding or removing selection from the object, ignore hitting selection axis. - hitInfo.bIgnoreAxis = true; - } - - if (dsMode == CDeepSelection::DSM_POP) - { - m_pDeepSelection->Reset(true); - m_pDeepSelection->SetMode(dsMode); - hitInfo.pDeepSelection = m_pDeepSelection; - } - else if (dsMode == CDeepSelection::DSM_CYCLE) - { - if (!m_pDeepSelection->OnCycling(point)) - { - // Start of the deep selection cycling mode. - m_pDeepSelection->Reset(false); - m_pDeepSelection->SetMode(dsMode); - hitInfo.pDeepSelection = m_pDeepSelection; - } - } - else - { - if (m_pDeepSelection->GetPreviousMode() == CDeepSelection::DSM_NONE) - { - m_pDeepSelection->Reset(true); - } - - m_pDeepSelection->SetMode(CDeepSelection::DSM_NONE); - hitInfo.pDeepSelection = 0; - } - - if (view->HitTest(point, hitInfo)) - { - if (hitInfo.axis != 0) - { - GetIEditor()->SetAxisConstraints((AxisConstrains)hitInfo.axis); - bLockSelection = true; - } - if (hitInfo.axis != 0) - { - view->SetAxisConstrain(hitInfo.axis); - } - - - ////////////////////////////////////////////////////////////////////////// - // Deep Selection - CheckDeepSelection(hitInfo, view); - } - - CBaseObject* hitObj = hitInfo.object; - - int editMode = GetIEditor()->GetEditMode(); - - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - - if (hitObj) - { - Matrix34 tm = hitInfo.object->GetWorldTM(); - tm.OrthonormalizeFast(); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - if (hitInfo.object->GetParent()) - { - Matrix34 parentTM = hitInfo.object->GetParent()->GetWorldTM(); - parentTM.OrthonormalizeFast(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - else - { - Matrix34 parentTM; - parentTM.SetIdentity(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - userTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - Matrix34 viewTM = view->GetViewTM(); - viewTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_VIEW, viewTM); - } - else - { - Matrix34 tm; - tm.SetIdentity(); - tm.SetTranslation(pos); - userTM.SetTranslation(pos); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - view->SetConstructionMatrix(COORDS_PARENT, tm); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - } - - if (editMode != eEditModeTool) - { - // Check for Move to position. - if (bCtrlClick && bShiftClick && !hitInfo.object) - { - // Ctrl-Click on terrain will move selected objects to specified location. - MoveSelectionToPos(view, pos, bAltClick, point); - bLockSelection = true; - } - else if (bCtrlClick && bShiftClick && hitInfo.object) - { - const int nPickFlag = CSurfaceInfoPicker::ePOG_All; - view->BeginUndo(); - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - const int numObjects = pSelection->GetCount(); - for (int objectIndex = 0;objectIndex < numObjects;++objectIndex) - { - CBaseObject* m_curObj = pSelection->GetObject(objectIndex); - CSurfaceInfoPicker::CExcludedObjects excludeObjects; - excludeObjects.Add(m_curObj); - SRayHitInfo hitInfo2; - CSurfaceInfoPicker surfacePicker; - if (surfacePicker.Pick(point, hitInfo2, &excludeObjects, nPickFlag)) - { - m_curObj->SetPos(hitInfo2.vHitPos); - if (bAltClick) - { - Quat nq; - Vec3 zaxis = m_curObj->GetRotation() * Vec3(AZ::Vector3::CreateAxisZ()); - zaxis.Normalize(); - nq.SetRotationV0V1(zaxis, hitInfo2.vHitNormal); - m_curObj->SetRotation(nq * m_curObj->GetRotation()); - } - } - - } - AzToolsFramework::ScopedUndoBatch undo("Transform"); - view->AcceptUndo("Move Selection"); - bLockSelection = true; - } - } - - if (editMode == eEditModeMove) - { - if (!bNoRemoveSelection) - { - SetCommandMode(MoveMode); - } - - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (editMode == eEditModeRotate) - { - if (!bNoRemoveSelection) - { - SetCommandMode(RotateMode); - } - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (editMode == eEditModeScale) - { - if (!bNoRemoveSelection) - { - GetIEditor()->GetSelection()->StartScaling(); - SetCommandMode(ScaleMode); - } - - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (hitObj != 0 && GetIEditor()->GetSelectedObject() == hitObj && !bAddSelect && !bUnselect) - { - bLockSelection = true; - } - - if (!bLockSelection) - { - // If not selection locked. - view->BeginUndo(); - - if (!bNoRemoveSelection) - { - // Current selection should be cleared - numUnselected = GetIEditor()->GetObjectManager()->ClearSelection(); - } - - if (hitObj) - { - numSelected = 1; - - if (!bUnselect) - { - if (hitObj->IsSelected()) - { - bUnselect = true; - } - } - - if (!bUnselect) - { - GetIEditor()->GetObjectManager()->SelectObject(hitObj, true); - } - else - { - GetIEditor()->GetObjectManager()->UnselectObject(hitObj); - } - } - if (view->IsUndoRecording()) - { - // When a designer object is selected, the update of the designer object can cause a change of a edit tool, which will makes this objectmode tool pointer invalid. - // so the update of objects must run on only pure idle time. - // view->AcceptUndo method calls the OnIdle() function in the app, which this is not a right timing to updates all, I think. - Jaesik Hwang. - GetIEditor()->GetObjectManager()->SetSkipUpdate(true); - view->AcceptUndo("Select Object(s)"); - GetIEditor()->GetObjectManager()->SetSkipUpdate(false); - } - - if ((numSelected == 0 || editMode == eEditModeSelect)) - { - // If object is not selected. - // Capture mouse input for this window. - SetCommandMode(SelectMode); - } - } - - if (GetCommandMode() == MoveMode || - GetCommandMode() == RotateMode || - GetCommandMode() == ScaleMode) - { - view->BeginUndo(); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - } - - ////////////////////////////////////////////////////////////////////////// - // Change cursor, must be before Capture mouse. - ////////////////////////////////////////////////////////////////////////// - SetObjectCursor(view, hitObj, true); - - ////////////////////////////////////////////////////////////////////////// - view->CaptureMouse(); - ////////////////////////////////////////////////////////////////////////// - - UpdateStatusText(); - - m_bTransformChanged = false; - - if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_POP) - { - return OnLButtonUp(view, nFlags, point); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonUp(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore clicks while in game. - return true; - } - - if (m_bTransformChanged) - { - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - if (pSelection) - { - pSelection->FinishChanges(); - } - m_bTransformChanged = false; - } - - if (GetCommandMode() == ScaleMode) - { - Vec3 scale; - GetIEditor()->GetSelection()->FinishScaling(GetScale(view, point, scale), - GetIEditor()->GetReferenceCoordSys()); - } - - if (GetCommandMode() == MoveMode) - { - m_bDragThresholdExceeded = false; - } - - // Reset the status bar caption - GetIEditor()->SetStatusText("Ready"); - - ////////////////////////////////////////////////////////////////////////// - if (view->IsUndoRecording()) - { - if (GetCommandMode() == MoveMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Move"); - } - view->AcceptUndo("Move Selection"); - } - else if (GetCommandMode() == RotateMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Rotate"); - } - view->AcceptUndo("Rotate Selection"); - } - else if (GetCommandMode() == ScaleMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Scale"); - } - view->AcceptUndo("Scale Selection"); - } - else - { - view->CancelUndo(); - } - } - ////////////////////////////////////////////////////////////////////////// - - if (GetCommandMode() == SelectMode && (!GetIEditor()->IsSelectionLocked())) - { - const bool bUnselect = (Qt::AltModifier & QApplication::queryKeyboardModifiers()); - QRect selectRect = view->GetSelectionRectangle(); - if (!selectRect.isEmpty()) - { - // Ignore too small rectangles. - if (selectRect.width() > 5 && selectRect.height() > 5) - { - GetIEditor()->GetObjectManager()->SelectObjectsInRect(view, selectRect, !bUnselect); - UpdateStatusText(); - } - } - - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - AABB box; - GetIEditor()->GetSelectedRegion(box); - - ////////////////////////////////////////////////////////////////////////// - GetIEditor()->ClearSelection(); - } - } - // Release the restriction of the cursor - view->ReleaseMouse(); - - if (GetCommandMode() == ScaleMode || GetCommandMode() == MoveMode || GetCommandMode() == RotateMode) - { - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, - selectedEntities); - } - - if (GetIEditor()->GetEditMode() != eEditModeSelectArea) - { - view->ResetSelectionRegion(); - } - // Reset selected rectangle. - view->SetSelectionRectangle(QRect()); - - // Restore default editor axis constrain. - if (GetIEditor()->GetAxisConstrains() != view->GetAxisConstrain()) - { - view->SetAxisConstrain(GetIEditor()->GetAxisConstrains()); - } - - SetCommandMode(NothingMode); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point) -{ - IEditor* editor = GetIEditor(); - - // If shift clicked, Move the camera to this place. - if (nFlags & MK_SHIFT) - { - // Get the heightmap coordinates for the click position - Vec3 v = view->ViewToWorld(point); - if (!(v.x == 0 && v.y == 0 && v.z == 0)) - { - Matrix34 tm = view->GetViewTM(); - Vec3 p = tm.GetTranslation(); - float height = p.z - editor->GetTerrainElevation(p.x, p.y); - if (height < 1) - { - height = 1; - } - p.x = v.x; - p.y = v.y; - p.z = editor->GetTerrainElevation(p.x, p.y) + height; - tm.SetTranslation(p); - view->SetViewTM(tm); - } - } - else - { - // Check if double clicked on object. - HitContext hitInfo; - view->HitTest(point, hitInfo); - - if (CBaseObject* hitObj = hitInfo.object) - { - // check if the object is an AZ::Entity - if ((hitObj->GetType() == OBJTYPE_AZENTITY)) - { - if (CRenderViewport* renderViewport = viewport_cast(view)) - { - // if we double clicked on an AZ::Entity/Component, build a mouse interaction and send a double - // click event to the EditorInteractionSystemViewportSelectionRequestBus. if we have double clicked - // on a component supporting ComponentMode, we will enter it. note: this is to support entering - // ComponentMode with a double click using the old viewport interaction model - const auto mouseInteraction = renderViewport->BuildMouseInteraction( - Qt::LeftButton, QGuiApplication::queryKeyboardModifiers(), - renderViewport->ViewportToWidget(point)); - - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - using AzToolsFramework::ViewportInteraction::MouseInteractionEvent; - using AzToolsFramework::ViewportInteraction::MouseEvent; - - EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, - MouseInteractionEvent(mouseInteraction, MouseEvent::DoubleClick)); - } - } - - // Fire double click event on hit object. - hitObj->OnEvent(EVENT_DBLCLICK); - } - else - { - if (!editor->IsSelectionLocked()) - { - editor->GetObjectManager()->ClearSelection(); - } - } - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnRButtonDown([[maybe_unused]] CViewport* view, [[maybe_unused]] int nFlags, [[maybe_unused]] const QPoint& point) -{ - if (gSettings.viewports.bEnableContextMenu && !GetIEditor()->IsInSimulationMode()) - { - m_openContext = true; - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnRButtonUp(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - if (m_openContext) - { - bool selectionLocked = GetIEditor()->IsSelectionLocked(); - - // Check if right clicked on object. - HitContext hitInfo; - hitInfo.bIgnoreAxis = true; // ignore gizmo - view->HitTest(point, hitInfo); - - QPointer object; - - if (selectionLocked) - { - if (hitInfo.object) - { - // Save so we can use this for the context menu later - object = hitInfo.object; - } - } - else - { - Vec3 pos = view->SnapToGrid(view->ViewToWorld(point)); - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - - if (hitInfo.object) - { - Matrix34 tm = hitInfo.object->GetWorldTM(); - tm.OrthonormalizeFast(); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - if (hitInfo.object->GetParent()) - { - Matrix34 parentTM = hitInfo.object->GetParent()->GetWorldTM(); - parentTM.OrthonormalizeFast(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - else - { - Matrix34 parentTM; - parentTM.SetIdentity(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - userTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - Matrix34 viewTM = view->GetViewTM(); - viewTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_VIEW, viewTM); - - CSelectionGroup* selections = GetIEditor()->GetObjectManager()->GetSelection(); - - // hit object has not been selected - if (!selections->IsContainObject(hitInfo.object)) - { - view->BeginUndo(); - GetIEditor()->GetObjectManager()->ClearSelection(); - GetIEditor()->GetObjectManager()->SelectObject(hitInfo.object, true); - view->AcceptUndo("Select Object(s)"); - } - - // Save so we can use this for the context menu later - object = hitInfo.object; - } - else - { - Matrix34 tm; - tm.SetIdentity(); - tm.SetTranslation(pos); - userTM.SetTranslation(pos); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - view->SetConstructionMatrix(COORDS_PARENT, tm); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - view->BeginUndo(); - GetIEditor()->GetObjectManager()->ClearSelection(); - view->AcceptUndo("Select Object(s)"); - } - } - - // CRenderViewport hides the cursor when the mouse button is pressed - // and shows it when button is released. If we exec the context menu directly, then we block - // and the cursor stays invisible while the menu is open so instead, we queue it to happen - // after the mouse button release is finished - QTimer::singleShot(0, this, [point, view, object]() - { - QMenu menu(viewport_cast(view)); - - if (object) - { - object->OnContextMenu(&menu); - } - - // Populate global context menu. - int contextMenuFlag = 0; - EBUS_EVENT(AzToolsFramework::EditorEvents::Bus, - PopulateEditorGlobalContextMenu, - &menu, - AZ::Vector2(static_cast(point.x()), static_cast(point.y())), - contextMenuFlag); - - if (!menu.isEmpty()) - { - menu.exec(QCursor::pos()); - } - }); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMButtonDown(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - if (GetIEditor()->GetGameEngine()->GetSimulationMode()) - { - // Get control key status. - const bool bCtrlClick = (Qt::ControlModifier & QApplication::queryKeyboardModifiers()); - - if (bCtrlClick) - { - // In simulation mode awake objects under the cursor when Ctrl+MButton pressed. - AwakeObjectAtPoint(view, point); - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::AwakeObjectAtPoint(CViewport* view, const QPoint& point) -{ - // In simulation mode awake objects under the cursor. - // Check if double clicked on object. - HitContext hitInfo; - view->HitTest(point, hitInfo); - CBaseObject* hitObj = hitInfo.object; - if (hitObj) - { - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point) -{ - view->BeginUndo(); - // Find center of selection. - Vec3 center = GetIEditor()->GetSelection()->GetCenter(); - GetIEditor()->GetSelection()->Move(pos - center, CSelectionGroup::eMS_None, true, point); - - if (align) - { - GetIEditor()->GetSelection()->Align(); - } - - // This will capture any entity state changes that occurred - // during the move. - { - AzToolsFramework::ScopedUndoBatch undo("Transform"); - } - - view->AcceptUndo("Move Selection"); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMouseMove(CViewport* view, int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore while in game. - return true; - } - - // Has the mouse been intentionally moved or could this be a small jump in movement due to right clicking? - if (std::abs(m_prevMousePos.x() - point.x()) > 2 || std::abs(m_prevMousePos.y() - point.y()) > 2) - { - // This was an intentional mouse movement, disable the context menu - m_openContext = false; - } - m_prevMousePos = point; - SetObjectCursor(view, 0); - - // get world/local coordinate system setting. - int coordSys = GetIEditor()->GetReferenceCoordSys(); - - // get current axis constrains. - if (GetCommandMode() == MoveMode) - { - if (!m_bDragThresholdExceeded) - { - int halfLength = gSettings.viewports.nDragSquareSize / 2; - QRect rcDrag(m_cMouseDownPos, QSize(0,0)); - rcDrag.adjust(-halfLength, -halfLength, halfLength, halfLength); - - if (!rcDrag.contains(point)) - { - m_bDragThresholdExceeded = true; - m_lastValidMoveVector = Vec3(0, 0, 0); - } - else - { - return true; - } - } - - GetIEditor()->RestoreUndo(); - - Vec3 v; - //m_cMouseDownPos = point; - CSelectionGroup::EMoveSelectionFlag selectionFlag = CSelectionGroup::eMS_None; - if (view->GetAxisConstrain() == AXIS_TERRAIN) - { - selectionFlag = CSelectionGroup::eMS_FollowTerrain; - Vec3 p1 = view->SnapToGrid(view->ViewToWorld(m_cMouseDownPos)); - Vec3 p2 = view->SnapToGrid(view->ViewToWorld(point)); - v = p2 - p1; - v.z = 0; - m_lastValidMoveVector = v; - } - else - { - Vec3 p1 = view->MapViewToCP(m_cMouseDownPos); - Vec3 p2 = view->MapViewToCP(point); - - if (p1.IsZero() || p2.IsZero()) - { - v = m_lastValidMoveVector; - } - else - { - v = view->GetCPVector(p1, p2); - m_lastValidMoveVector = v; - } - - //Matrix invParent = m_parentConstructionMatrix; - //invParent.Invert(); - //p1 = invParent.TransformVector(p1); - //p2 = invParent.TransformVector(p2); - //v = p2 - p1; - } - - if ((nFlags & MK_CONTROL) && !(nFlags & MK_SHIFT)) - { - selectionFlag = CSelectionGroup::eMS_FollowGeometryPosNorm; - } - - if (!v.IsEquivalent(Vec3(0, 0, 0))) - { - m_bTransformChanged = true; - } - - CTrackViewSequence* pSequence = GetIEditor()->GetAnimation()->GetSequence(); - { - CTrackViewSequenceNoNotificationContext context(pSequence); - GetIEditor()->GetSelection()->Move(v, selectionFlag, coordSys, point); - } - - if (pSequence) - { - pSequence->OnKeysChanged(); - } - - return true; - } - else if (GetCommandMode() == ScaleMode) - { - GetIEditor()->RestoreUndo(); - Vec3 scale; - GetIEditor()->GetSelection()->Scale(GetScale(view, point, scale), coordSys); - if (!scale.IsEquivalent(Vec3(0, 0, 0))) - { - m_bTransformChanged = true; - } - } - else if (GetCommandMode() == SelectMode) - { - // Ignore select when selection locked. - if (GetIEditor()->IsSelectionLocked()) - { - return true; - } - - QRect rc(m_cMouseDownPos, point - QPoint(1, 1)); - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - view->OnDragSelectRectangle(rc, false); - } - else - { - view->SetSelectionRectangle(rc); - } - //else - //OnDragSelectRectangle( CPoint(rc.left,rc.top),CPoint(rc.right,rc.bottom),true ); - } - - if (!(nFlags & MK_RBUTTON || nFlags & MK_MBUTTON)) - { - // Track mouse movements. - HitContext hitInfo; - if (view->HitTest(point, hitInfo)) - { - SetObjectCursor(view, hitInfo.object); - } - - HandleMoveByFaceNormal(hitInfo); - } - - if ((nFlags & MK_MBUTTON) && GetIEditor()->GetGameEngine()->GetSimulationMode()) - { - // Get control key status. - const bool bCtrlClick = (Qt::ControlModifier & QApplication::queryKeyboardModifiers()); - - if (bCtrlClick) - { - // In simulation mode awake objects under the cursor when Ctrl+MButton pressed. - AwakeObjectAtPoint(view, point); - } - } - - UpdateStatusText(); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMouseLeave(CViewport* view) -{ - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore while in game. - return true; - } - - m_openContext = false; - SetObjectCursor(view, 0); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::SetObjectCursor(CViewport* view, CBaseObject* hitObj, [[maybe_unused]] bool bChangeNow) -{ - EStdCursor cursor = STD_CURSOR_DEFAULT; - QString m_cursorStr; - QString supplementaryCursor = ""; - - CBaseObject* pMouseOverObject = NULL; - if (!GuidUtil::IsEmpty(m_MouseOverObject)) - { - pMouseOverObject = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject); - } - - //HCURSOR hPrevCursor = m_hCurrCursor; - if (pMouseOverObject) - { - pMouseOverObject->SetHighlight(false); - } - if (hitObj) - { - m_MouseOverObject = hitObj->GetId(); - } - else - { - m_MouseOverObject = GUID_NULL; - } - pMouseOverObject = hitObj; - bool bHitSelectedObject = false; - if (pMouseOverObject) - { - if (GetCommandMode() != SelectMode && !GetIEditor()->IsSelectionLocked()) - { - if (pMouseOverObject->CanBeHightlighted()) - { - pMouseOverObject->SetHighlight(true); - } - - m_cursorStr = pMouseOverObject->GetName(); - - QString comment(pMouseOverObject->GetComment()); - if (!comment.isEmpty()) - { - m_cursorStr += "\n"; - m_cursorStr += comment; - } - - QString warnings(pMouseOverObject->GetWarningsText()); - if (!warnings.isEmpty()) - { - m_cursorStr += warnings; - } - - cursor = STD_CURSOR_HIT; - if (pMouseOverObject->IsSelected()) - { - bHitSelectedObject = true; - } - - if (pMouseOverObject->GetType() == OBJTYPE_AZENTITY) - { - CComponentEntityObject* componentEntity = static_cast(pMouseOverObject); - - bool isEditorOnly = false; - AzToolsFramework::EditorOnlyEntityComponentRequestBus::EventResult(isEditorOnly, componentEntity->GetAssociatedEntityId(), &AzToolsFramework::EditorOnlyEntityComponentRequests::IsEditorOnlyEntity); - AZ::Entity* entity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, componentEntity->GetAssociatedEntityId()); - const bool isInitiallyActive = entity ? entity->IsRuntimeActiveByDefault() : true; - - if (isEditorOnly) - { - supplementaryCursor = "\n[" + QObject::tr("Editor Only") + "]"; - } - else if (!isInitiallyActive) - { - supplementaryCursor = "\n[" + QObject::tr("Inactive") + "]"; - } - } - } - - QString tooltip = pMouseOverObject->GetTooltip(); - if (!tooltip.isEmpty()) - { - m_cursorStr += "\n"; - m_cursorStr += tooltip; - } - ; - } - else - { - m_cursorStr = ""; - cursor = STD_CURSOR_DEFAULT; - } - // Get control key status. - const auto modifiers = QApplication::queryKeyboardModifiers(); - const bool bAltClick = (Qt::AltModifier & modifiers); - const bool bCtrlClick = (Qt::ControlModifier & modifiers); - const bool bShiftClick = (Qt::ShiftModifier & modifiers); - - bool bAddSelect = bCtrlClick && !bShiftClick; - bool bUnselect = bAltClick; - bool bNoRemoveSelection = bAddSelect || bUnselect; - - bool bLockSelection = GetIEditor()->IsSelectionLocked(); - - if (GetCommandMode() == SelectMode || GetCommandMode() == NothingMode) - { - if (bAddSelect) - { - cursor = STD_CURSOR_SEL_PLUS; - } - if (bUnselect) - { - cursor = STD_CURSOR_SEL_MINUS; - } - - if ((bHitSelectedObject && !bNoRemoveSelection) || bLockSelection) - { - int editMode = GetIEditor()->GetEditMode(); - if (editMode == eEditModeMove) - { - cursor = STD_CURSOR_MOVE; - } - else if (editMode == eEditModeRotate) - { - cursor = STD_CURSOR_ROTATE; - } - else if (editMode == eEditModeScale) - { - cursor = STD_CURSOR_SCALE; - } - } - } - else if (GetCommandMode() == MoveMode) - { - cursor = STD_CURSOR_MOVE; - } - else if (GetCommandMode() == RotateMode) - { - cursor = STD_CURSOR_ROTATE; - } - else if (GetCommandMode() == ScaleMode) - { - cursor = STD_CURSOR_SCALE; - } - - AZ::u32 cursorId = static_cast(cursor); - AZStd::string cursorStr = m_cursorStr.toUtf8().data(); - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, - UpdateObjectModeCursor, - cursorId, - cursorStr); - cursor = static_cast(cursorId); - m_cursorStr = cursorStr.c_str(); - - view->SetCurrentCursor(cursor, m_cursorStr); - view->SetSupplementaryCursorStr(supplementaryCursor); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass("EditTool.ObjectMode", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::UpdateStatusText() -{ - QString str; - int nCount = GetIEditor()->GetSelection()->GetCount(); - if (nCount > 0) - { - str = tr("%1 Object(s) Selected").arg(nCount); - } - else - { - str = tr("No Selection"); - } - SetStatusText(str); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::CheckDeepSelection(HitContext& hitContext, CViewport* view) -{ - if (hitContext.pDeepSelection) - { - m_pDeepSelection->CollectCandidate(hitContext.dist, gSettings.deepSelectionSettings.fRange); - } - - if (m_pDeepSelection->GetCandidateObjectCount() > 1) - { - // Deep Selection Pop Mode - if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_POP) - { - // Show a sorted pop-up menu for selecting a bone. - QMenu popUpDeepSelect(qobject_cast(view->qobject())); - - for (int i = 0; i < m_pDeepSelection->GetCandidateObjectCount(); ++i) - { - QAction* action = popUpDeepSelect.addAction(QString(m_pDeepSelection->GetCandidateObject(i)->GetName())); - action->setData(i); - } - - QAction* userSelection = popUpDeepSelect.exec(QCursor::pos()); - if (userSelection) - { - int nSelect = userSelection->data().toInt(); - - // Update HitContext hitInfo. - hitContext.object = m_pDeepSelection->GetCandidateObject(nSelect); - m_pDeepSelection->ExcludeHitTest(nSelect); - } - } - else if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_CYCLE) - { - int selPos = m_pDeepSelection->GetCurrentSelectPos(); - hitContext.object = m_pDeepSelection->GetCandidateObject(selPos + 1); - m_pDeepSelection->ExcludeHitTest(selPos + 1); - } - } -} - -Vec3& CObjectMode::GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale) -{ - float ay = 1.0f - 0.01f * (point.y() - m_cMouseDownPos.y()); - - if (ay < 0.01f) - { - ay = 0.01f; - } - - Vec3 scl(ay, ay, ay); - - int axisConstrain = view->GetAxisConstrain(); - - if (axisConstrain < AXIS_XYZ && GetIEditor()->IsAxisVectorLocked()) - { - axisConstrain = AXIS_XYZ; - } - - switch (axisConstrain) - { - case AXIS_X: - scl(ay, 1, 1); - break; - case AXIS_Y: - scl(1, ay, 1); - break; - case AXIS_Z: - scl(1, 1, ay); - break; - case AXIS_XY: - scl(ay, ay, ay); - break; - case AXIS_XZ: - scl(ay, ay, ay); - break; - case AXIS_YZ: - scl(ay, ay, ay); - break; - case AXIS_XYZ: - scl(ay, ay, ay); - break; - case AXIS_TERRAIN: - scl(ay, ay, ay); - break; - } - ; - - OutScale = scl; - - return OutScale; -} - -////////////////////////////////////////////////////////////////////////// -// This callback is currently called only to handle the case of the 'move by the face normal'. -// Other movements of the object are handled in the 'CObjectMode::OnMouseMove()' method. -void CObjectMode::OnManipulatorDrag(CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, QPoint& point0, [[maybe_unused]] QPoint& point1, const Vec3& value) -{ - RefCoordSys coordSys = GetIEditor()->GetReferenceCoordSys(); - int editMode = GetIEditor()->GetEditMode(); - - if (editMode == eEditModeMove) - { - GetIEditor()->RestoreUndo(); - CSelectionGroup* pSelGrp = GetIEditor()->GetSelection(); - - CSelectionGroup::EMoveSelectionFlag selectionFlag = view->GetAxisConstrain() == AXIS_TERRAIN ? CSelectionGroup::eMS_FollowTerrain : CSelectionGroup::eMS_None; - pSelGrp->Move(value, selectionFlag, coordSys, point0); - - if (m_pHitObject) - { - UpdateMoveByFaceNormGizmo(m_pHitObject); - } - } -} - -void CObjectMode::HandleMoveByFaceNormal([[maybe_unused]] HitContext& hitInfo) -{ - const bool bNKeyPressed = CheckVirtualKey(Qt::Key_N); - if (m_bMoveByFaceNormManipShown && !bNKeyPressed) - { - HideMoveByFaceNormGizmo(); - } -} - -void CObjectMode::UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject) -{ - Matrix34 refFrame; - refFrame.SetIdentity(); - SubObjectSelectionReferenceFrameCalculator calculator(SO_ELEM_FACE); - pHitObject->CalculateSubObjectSelectionReferenceFrame(&calculator); - if (calculator.GetFrame(refFrame) == false) - { - HideMoveByFaceNormGizmo(); - } - else - { - ITransformManipulator* pManipulator = GetIEditor()->ShowTransformManipulator(true); - m_bMoveByFaceNormManipShown = true; - m_pHitObject = pHitObject; - - Matrix34 parentTM = pHitObject->GetWorldTM(); - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - parentTM.SetTranslation(refFrame.GetTranslation()); - userTM.SetTranslation(refFrame.GetTranslation()); - pManipulator->SetTransformation(COORDS_LOCAL, refFrame); - pManipulator->SetTransformation(COORDS_PARENT, parentTM); - pManipulator->SetTransformation(COORDS_USERDEFINED, userTM); - pManipulator->SetAlwaysUseLocal(true); - } -} - -void CObjectMode::HideMoveByFaceNormGizmo() -{ - GetIEditor()->ShowTransformManipulator(false); - m_bMoveByFaceNormManipShown = false; - m_pHitObject = NULL; -} - -#include - diff --git a/Code/Sandbox/Editor/EditMode/ObjectMode.h b/Code/Sandbox/Editor/EditMode/ObjectMode.h deleted file mode 100644 index a7919b2c47..0000000000 --- a/Code/Sandbox/Editor/EditMode/ObjectMode.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Object edit mode describe viewport input behavior when operating on objects. - - -#ifndef CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H -#define CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H -#pragma once - -// {87109FED-BDB5-4874-936D-338400079F58} -DEFINE_GUID(OBJECT_MODE_GUID, 0x87109fed, 0xbdb5, 0x4874, 0x93, 0x6d, 0x33, 0x84, 0x0, 0x7, 0x9f, 0x58); - -#include "EditTool.h" - -class CBaseObject; -class CDeepSelection; -/*! -* CObjectMode is an abstract base class for All Editing Tools supported by Editor. -* Edit tools handle specific editing modes in viewports. -*/ -class SANDBOX_API CObjectMode - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CObjectMode(QObject* parent = nullptr); - virtual ~CObjectMode(); - - static const GUID& GetClassID() { return OBJECT_MODE_GUID; } - - // Registration function. - static void RegisterTool(CRegistrationContext& rc); - - ////////////////////////////////////////////////////////////////////////// - // CEditTool implementation. - ////////////////////////////////////////////////////////////////////////// - virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {}; - virtual void EndEditParams(); - virtual void Display(struct DisplayContext& dc); - virtual void DisplaySelectionPreview(struct DisplayContext& dc); - virtual void DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject); - void DisplayExtraLightInfo(struct DisplayContext& dc); - - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; }; - - virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, QPoint& p0, QPoint& p1, const Vec3& value) override; - - bool IsUpdateUIPanel() override { return true; } - -protected: - enum ECommandMode - { - NothingMode = 0, - ScrollZoomMode, - SelectMode, - MoveMode, - RotateMode, - ScaleMode, - ScrollMode, - ZoomMode, - }; - - virtual bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnRButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnRButtonUp(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMouseLeave(CViewport* view); - - void SetCommandMode(ECommandMode mode) { m_commandMode = mode; } - ECommandMode GetCommandMode() const { return m_commandMode; } - - //! Ctrl-Click in move mode to move selected objects to given pos. - void MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point); - void SetObjectCursor(CViewport* view, CBaseObject* hitObj, bool bChangeNow = false); - - virtual void DeleteThis() { delete this; }; - - void UpdateStatusText(); - void AwakeObjectAtPoint(CViewport* view, const QPoint& point); - - void HideMoveByFaceNormGizmo(); - void HandleMoveByFaceNormal(HitContext& hitInfo); - void UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject); - -protected: - - bool m_openContext; - -private: - void CheckDeepSelection(HitContext& hitContext, CViewport* view); - Vec3& GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale); - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QPoint m_cMouseDownPos; - bool m_bDragThresholdExceeded; - ECommandMode m_commandMode; - - GUID m_MouseOverObject; - typedef std::vector TGuidContainer; - TGuidContainer m_PreviewGUIDs; - - _smart_ptr m_pDeepSelection; - - bool m_bMoveByFaceNormManipShown; - CBaseObject* m_pHitObject; - - bool m_bTransformChanged; - - QPoint m_prevMousePos = QPoint(0, 0); - - Vec3 m_lastValidMoveVector = Vec3(0, 0, 0); - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - - - -#endif // CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H diff --git a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp b/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp deleted file mode 100644 index a0a5492f55..0000000000 --- a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#if defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include "VertexSnappingModeTool.h" - -// Editor -#include "Settings.h" -#include "Viewport.h" -#include "SurfaceInfoPicker.h" -#include "Material/Material.h" -#include "Util/KDTree.h" - - -// {3e008046-9269-41d7-82e2-07ffd7254c10} -DEFINE_GUID(VERTEXSNAPPING_MODE_GUID, 0x3e008046, 0x9269, 0x41d7, 0x82, 0xe2, 0x07, 0xff, 0xd7, 0x25, 0x4c, 0x10); - -bool FindNearestVertex(CBaseObject* pObject, CKDTree* pTree, const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, Vec3& outPos, Vec3& vOutHitPosOnCube) -{ - Matrix34 worldInvTM = pObject->GetWorldTM().GetInverted(); - Vec3 vRaySrc = worldInvTM.TransformPoint(vWorldRaySrc); - Vec3 vRayDir = worldInvTM.TransformVector(vWorldRayDir); - Vec3 vLocalCameraPos = worldInvTM.TransformPoint(gEnv->pRenderer->GetCamera().GetPosition()); - Vec3 vPos; - Vec3 vHitPosOnCube; - - if (pTree) - { - if (pTree->FindNearestVertex(vRaySrc, vRayDir, gSettings.vertexSnappingSettings.vertexCubeSize, vLocalCameraPos, vPos, vHitPosOnCube)) - { - outPos = pObject->GetWorldTM().TransformPoint(vPos); - vOutHitPosOnCube = pObject->GetWorldTM().TransformPoint(vHitPosOnCube); - return true; - } - } - else - { - // for objects without verts, the pivot is the nearest vertex - // return true if the ray hits the bounding box - outPos = pObject->GetWorldPos(); - - AABB bbox; - pObject->GetBoundBox(bbox); - if (bbox.IsContainPoint(vWorldRaySrc)) - { - // if ray starts inside bounding box, reject cases where pivot is behind the ray - float hitDistAlongRay = vWorldRayDir.Dot(outPos - vWorldRaySrc); - if (hitDistAlongRay >= 0.f) - { - vHitPosOnCube = vWorldRaySrc + (vWorldRayDir * hitDistAlongRay); - return true; - } - } - else if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, bbox, vOutHitPosOnCube)) - { - return true; - } - } - - return false; -} - -CVertexSnappingModeTool::CVertexSnappingModeTool() -{ - m_modeStatus = eVSS_SelectFirstVertex; - m_bHit = false; -} - -CVertexSnappingModeTool::~CVertexSnappingModeTool() -{ - std::map::iterator ii = m_ObjectKdTreeMap.begin(); - for (; ii != m_ObjectKdTreeMap.end(); ++ii) - { - delete ii->second; - } -} - -const GUID& CVertexSnappingModeTool::GetClassID() -{ - return VERTEXSNAPPING_MODE_GUID; -} - -void CVertexSnappingModeTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass("EditTool.VertexSnappingMode", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -bool CVertexSnappingModeTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - CBaseObjectPtr pExcludedObject = NULL; - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex) - { - pExcludedObject = m_SelectionInfo.m_pObject; - } - - m_bHit = HitTest(view, point, pExcludedObject, m_vHitVertex, m_pHitObject, m_Objects); - - if (event == eMouseLDown && m_bHit && m_pHitObject && m_modeStatus == eVSS_SelectFirstVertex) - { - m_modeStatus = eVSS_MoveSelectVertexToAnotherVertex; - m_SelectionInfo.m_pObject = m_pHitObject; - m_SelectionInfo.m_vPos = m_vHitVertex; - - GetIEditor()->BeginUndo(); - m_pHitObject->StoreUndo("Vertex Snapping", true); - - view->SetCapture(); - } - - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex) - { - if (event == eMouseLUp) - { - m_modeStatus = eVSS_SelectFirstVertex; - - GetIEditor()->AcceptUndo("Vertex Snapping"); - view->ReleaseMouse(); - } - else if ((flags & MK_LBUTTON) && event == eMouseMove) - { - Vec3 vOffset = m_SelectionInfo.m_pObject->GetWorldPos() - m_SelectionInfo.m_vPos; - m_SelectionInfo.m_pObject->SetWorldPos(m_vHitVertex + vOffset); - m_SelectionInfo.m_vPos = m_SelectionInfo.m_pObject->GetWorldPos() - vOffset; - } - } - - return true; -} - -bool CVertexSnappingModeTool::HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector& outObjects) -{ - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - m_DebugBoxes.clear(); - } - - pOutHitObject = NULL; - outObjects.clear(); - - // - // Collect valid objects that mouse is over - // - - CSurfaceInfoPicker picker; - CSurfaceInfoPicker::CExcludedObjects excludedObjects; - if (pExcludedObj) - { - excludedObjects.Add(pExcludedObj); - } - - int nPickFlag = CSurfaceInfoPicker::ePOG_Entity; - - std::vector penetratedObjects; - if (!picker.PickByAABB(point, nPickFlag, view, &excludedObjects, &penetratedObjects)) - { - return false; - } - - for (int i = 0, iCount(penetratedObjects.size()); i < iCount; ++i) - { - CMaterial* pMaterial = penetratedObjects[i]->GetMaterial(); - if (pMaterial) - { - QString matName = pMaterial->GetName(); - if (!QString::compare(matName, "Objects/sky/forest_sky_dome", Qt::CaseInsensitive)) - { - continue; - } - } - outObjects.push_back(penetratedObjects[i]); - } - - // - // Find the best vertex. - // - - Vec3 vWorldRaySrc, vWorldRayDir; - view->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir); - - std::vector::iterator ii = outObjects.begin(); - float fNearestDist = 3e10f; - Vec3 vNearestPos; - CBaseObjectPtr pNearestObject = NULL; - for (ii = outObjects.begin(); ii != outObjects.end(); ++ii) - { - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - // add to debug boxes: the penetrated nodes of each object's kd-tree - if (auto pTree = GetKDTree(*ii)) - { - Matrix34 invWorldTM = (*ii)->GetWorldTM().GetInverted(); - int nIndex = m_DebugBoxes.size(); - - Vec3 vLocalRaySrc = invWorldTM.TransformPoint(vWorldRaySrc); - Vec3 vLocalRayDir = invWorldTM.TransformVector(vWorldRayDir); - pTree->GetPenetratedBoxes(vLocalRaySrc, vLocalRayDir, m_DebugBoxes); - for (int i = nIndex; i < m_DebugBoxes.size(); ++i) - { - m_DebugBoxes[i].SetTransformedAABB((*ii)->GetWorldTM(), m_DebugBoxes[i]); - } - } - } - - // find the nearest vertex on this object - Vec3 vPos, vHitPosOnCube; - if (FindNearestVertex(*ii, GetKDTree(*ii), vWorldRaySrc, vWorldRayDir, vPos, vHitPosOnCube)) - { - // is this the best so far? - float fDistance = vHitPosOnCube.GetDistance(vWorldRaySrc); - if (fDistance < fNearestDist) - { - fNearestDist = fDistance; - vNearestPos = vPos; - pNearestObject = *ii; - } - } - } - - if (fNearestDist < 3e10f) - { - outHitPos = vNearestPos; - pOutHitObject = pNearestObject; - } - - // if the mouse is over the object's pivot, use that instead of a vertex - if (pOutHitObject) - { - Vec3 vPivotPos = pOutHitObject->GetWorldPos(); - Vec3 vPivotBox = GetCubeSize(view, pOutHitObject->GetWorldPos()); - AABB pivotAABB(vPivotPos - vPivotBox, vPivotPos + vPivotBox); - Vec3 vPosOnPivotCube; - if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, pivotAABB, vPosOnPivotCube)) - { - outHitPos = vPivotPos; - return true; - } - } - - return pOutHitObject && pOutHitObject == pNearestObject; -} - -Vec3 CVertexSnappingModeTool::GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const -{ - if (!pView) - { - return Vec3(0, 0, 0); - } - float fScreenFactor = pView->GetScreenScaleFactor(pos); - return gSettings.vertexSnappingSettings.vertexCubeSize * Vec3(fScreenFactor, fScreenFactor, fScreenFactor); -} - -void CVertexSnappingModeTool::Display(struct DisplayContext& dc) -{ - const ColorB SnappedColor(0xFF00FF00); - const ColorB PivotColor(0xFF2020FF); - const ColorB VertexColor(0xFFFFAAAA); - - // draw all objects under mouse - dc.SetColor(VertexColor); - for (int i = 0, iCount(m_Objects.size()); i < iCount; ++i) - { - AABB worldAABB; - m_Objects[i]->GetBoundBox(worldAABB); - if (!dc.view->IsBoundsVisible(worldAABB)) - { - continue; - } - - if (auto pStatObj = m_Objects[i]->GetIStatObj()) - { - DrawVertexCubes(dc, m_Objects[i]->GetWorldTM(), pStatObj); - } - else - { - dc.DrawWireBox(worldAABB.min, worldAABB.max); - } - } - - // draw object being moved - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex && m_SelectionInfo.m_pObject) - { - dc.SetColor(QColor(0xaa, 0xaa, 0xaa)); - if (auto pStatObj = m_SelectionInfo.m_pObject->GetIStatObj()) - { - DrawVertexCubes(dc, m_SelectionInfo.m_pObject->GetWorldTM(), pStatObj); - } - else - { - AABB bounds; - m_SelectionInfo.m_pObject->GetBoundBox(bounds); - dc.DrawWireBox(bounds.min, bounds.max); - } - } - - // draw pivot of hit object - if (m_pHitObject && (!m_bHit || m_bHit && !m_pHitObject->GetWorldPos().IsEquivalent(m_vHitVertex, 0.001f))) - { - dc.SetColor(PivotColor); - dc.DepthTestOff(); - - Vec3 vBoxSize = GetCubeSize(dc.view, m_pHitObject->GetWorldPos()) * 1.2f; - AABB vertexBox(m_pHitObject->GetWorldPos() - vBoxSize, m_pHitObject->GetWorldPos() + vBoxSize); - dc.DrawBall((vertexBox.min + vertexBox.max) * 0.5f, (vertexBox.max.x - vertexBox.min.x) * 0.5f); - - dc.DepthTestOn(); - } - - // draw the vertex (or pivot) that's being hit - if (m_bHit) - { - dc.DepthTestOff(); - dc.SetColor(SnappedColor); - Vec3 vBoxSize = GetCubeSize(dc.view, m_vHitVertex); - if (m_vHitVertex.IsEquivalent(m_pHitObject->GetWorldPos(), 0.001f)) - { - dc.DrawBall(m_vHitVertex, vBoxSize.x * 1.2f); - } - else - { - dc.DrawSolidBox(m_vHitVertex - vBoxSize, m_vHitVertex + vBoxSize); - } - dc.DepthTestOn(); - } - - // draw wireframe of hit object - if (m_pHitObject && m_pHitObject->GetIStatObj()) - { - SGeometryDebugDrawInfo dd; - dd.tm = m_pHitObject->GetWorldTM(); - dd.color = ColorB(250, 0, 250, 30); - dd.lineColor = ColorB(255, 255, 0, 160); - dd.bExtrude = true; - m_pHitObject->GetIStatObj()->DebugDraw(dd); - } - - // draw debug boxes - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - ColorB boxColor(40, 40, 40); - for (int i = 0, iCount(m_DebugBoxes.size()); i < iCount; ++i) - { - dc.SetColor(boxColor); - boxColor += ColorB(25, 25, 25); - dc.DrawWireBox(m_DebugBoxes[i].min, m_DebugBoxes[i].max); - } - } -} - -void CVertexSnappingModeTool::DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj) -{ - if (!pStatObj) - { - return; - } - - IIndexedMesh* pIndexedMesh = pStatObj->GetIndexedMesh(); - if (pIndexedMesh) - { - IIndexedMesh::SMeshDescription md; - pIndexedMesh->GetMeshDescription(md); - for (int k = 0; k < md.m_nVertCount; ++k) - { - Vec3 vPos(0, 0, 0); - if (md.m_pVerts) - { - vPos = md.m_pVerts[k]; - } - else if (md.m_pVertsF16) - { - vPos = md.m_pVertsF16[k].ToVec3(); - } - else - { - continue; - } - vPos = tm.TransformPoint(vPos); - Vec3 vBoxSize = GetCubeSize(dc.view, vPos); - if (!m_bHit || !m_vHitVertex.IsEquivalent(vPos, 0.001f)) - { - dc.DrawSolidBox(vPos - vBoxSize, vPos + vBoxSize); - } - } - } - - for (int i = 0, iSubStatObjNum(pStatObj->GetSubObjectCount()); i < iSubStatObjNum; ++i) - { - IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(i); - if (pSubObj) - { - DrawVertexCubes(dc, tm * pSubObj->localTM, pSubObj->pStatObj); - } - } -} - -CKDTree* CVertexSnappingModeTool::GetKDTree(CBaseObject* pObject) -{ - auto existingTree = m_ObjectKdTreeMap.find(pObject); - if (existingTree != m_ObjectKdTreeMap.end()) - { - return existingTree->second; - } - - // Don't build a kd-tree for objects without verts - CKDTree* pTree = nullptr; - if (auto pStatObj = pObject->GetIStatObj()) - { - pTree = new CKDTree(); - pTree->Build(pObject->GetIStatObj()); - } - - m_ObjectKdTreeMap[pObject] = pTree; - return pTree; -} - -#include diff --git a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h b/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h deleted file mode 100644 index 943f6bceb4..0000000000 --- a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H -#define CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H -#pragma once - -#include "EditTool.h" -#include "Objects/BaseObject.h" - -class CKDTree; -struct IDisplayViewport; - -class CVertexSnappingModeTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CVertexSnappingModeTool(); - ~CVertexSnappingModeTool(); - - static const GUID& GetClassID(); - - static void RegisterTool(CRegistrationContext& rc); - - void Display(DisplayContext& dc); - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - -protected: - - void DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj); - void DeleteThis(){ delete this; } - Vec3 GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const; - -private: - - using CEditTool::HitTest; - bool HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector& outObjects); - CKDTree* GetKDTree(CBaseObject* pObject); - - enum EVertexSnappingStatus - { - eVSS_SelectFirstVertex, - eVSS_MoveSelectVertexToAnotherVertex - }; - EVertexSnappingStatus m_modeStatus; - - struct SSelectionInfo - { - SSelectionInfo() - { - m_pObject = NULL; - m_vPos = Vec3(0, 0, 0); - } - CBaseObjectPtr m_pObject; - Vec3 m_vPos; - }; - - /// Info on object being moved (when in eVSS_MoveSelectVertexToAnotherVertex mode). - SSelectionInfo m_SelectionInfo; - - /// Objects that mouse is over - std::vector m_Objects; - - /// Position of vertex that mouse is hitting. - /// Invalid when m_bHit is false. - Vec3 m_vHitVertex; - - /// Whether the mouse hit test succeeded - bool m_bHit; - - /// Object that mouse is hitting - CBaseObjectPtr m_pHitObject; - - /// Boxes to render for debug drawing - std::vector m_DebugBoxes; - - /// For each object, a tree containing its vertices. - std::map m_ObjectKdTreeMap; -}; -#endif // CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H diff --git a/Code/Sandbox/Editor/EditTool.cpp b/Code/Sandbox/Editor/EditTool.cpp deleted file mode 100644 index 31a59aa58f..0000000000 --- a/Code/Sandbox/Editor/EditTool.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "EditTool.h" - -// Editor -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" - -////////////////////////////////////////////////////////////////////////// -// Class description. -////////////////////////////////////////////////////////////////////////// -class CEditTool_ClassDesc - : public CRefCountClassDesc -{ - virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; } - virtual REFGUID ClassID() - { - // {0A43AB8E-B1AE-44aa-93B1-229F73D58CA4} - static const GUID guid = { - 0xa43ab8e, 0xb1ae, 0x44aa, { 0x93, 0xb1, 0x22, 0x9f, 0x73, 0xd5, 0x8c, 0xa4 } - }; - return guid; - } - virtual QString ClassName() { return "EditTool.Default"; }; - virtual QString Category() { return "EditTool"; }; -}; -CEditTool_ClassDesc g_stdClassDesc; - -////////////////////////////////////////////////////////////////////////// -CEditTool::CEditTool(QObject* parent) - : QObject(parent) -{ - m_pClassDesc = &g_stdClassDesc; - m_nRefCount = 0; -}; - -////////////////////////////////////////////////////////////////////////// -void CEditTool::SetParentTool(CEditTool* pTool) -{ - m_pParentTool = pTool; -} - -////////////////////////////////////////////////////////////////////////// -CEditTool* CEditTool::GetParentTool() -{ - return m_pParentTool; -} - -////////////////////////////////////////////////////////////////////////// -void CEditTool::Abort() -{ - if (m_pParentTool) - { - GetIEditor()->SetEditTool(m_pParentTool); - } - else - { - GetIEditor()->SetEditTool(0); - } -} - -////////////////////////////////////////////////////////////////////////// -void CEditTool::GetAffectedObjects(DynArray& outAffectedObjects) -{ - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection == NULL) - { - return; - } - for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i) - { - outAffectedObjects.push_back(pSelection->GetObject(i)); - } -} - -#include diff --git a/Code/Sandbox/Editor/EditTool.h b/Code/Sandbox/Editor/EditTool.h deleted file mode 100644 index b9d937ae0d..0000000000 --- a/Code/Sandbox/Editor/EditTool.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_EDITTOOL_H -#define CRYINCLUDE_EDITOR_EDITTOOL_H - -#pragma once - -#if !defined(Q_MOC_RUN) -#include "QtViewPaneManager.h" -#endif - -class CViewport; -struct IClassDesc; -struct ITransformManipulator; -struct HitContext; - -enum EEditToolType -{ - EDIT_TOOL_TYPE_PRIMARY, - EDIT_TOOL_TYPE_SECONDARY, -}; - -/*! - * CEditTool is an abstract base class for All Editing Tools supported by Editor. - * Edit tools handle specific editing modes in viewports. - */ -class SANDBOX_API CEditTool - : public QObject -{ - Q_OBJECT -public: - explicit CEditTool(QObject* parent = nullptr); - - ////////////////////////////////////////////////////////////////////////// - // For reference counting. - ////////////////////////////////////////////////////////////////////////// - void AddRef() { m_nRefCount++; }; - void Release() - { - AZ_Assert(m_nRefCount > 0, "Negative ref count"); - if (--m_nRefCount == 0) - { - DeleteThis(); - } - }; - - //! Returns class description for this tool. - IClassDesc* GetClassDesc() const { return m_pClassDesc; } - - virtual void SetParentTool(CEditTool* pTool); - virtual CEditTool* GetParentTool(); - - virtual EEditToolType GetType() { return EDIT_TOOL_TYPE_PRIMARY; } - virtual EOperationMode GetMode() { return eOperationModeNone; } - - // Abort tool. - virtual void Abort(); - - // Accept tool. - virtual void Accept([[maybe_unused]] bool resetPosition = false) {} - - //! Status text displayed when this tool is active. - void SetStatusText(const QString& text) { m_statusText = text; }; - QString GetStatusText() { return m_statusText; }; - - // Description: - // Activates tool. - // Arguments: - // pPreviousTool - Previously active edit tool. - // Return: - // True if the tool can be activated, - virtual bool Activate([[maybe_unused]] CEditTool* pPreviousTool) { return true; }; - - //! Used to pass user defined data to edit tool from ToolButton. - virtual void SetUserData([[maybe_unused]] const char* key, [[maybe_unused]] void* userData) {}; - - //! Called when user starts using this tool. - //! Flags is comnination of ObjectEditFlags flags. - virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {}; - //! Called when user ends using this tool. - virtual void EndEditParams() {}; - - // Called each frame to display tool for given viewport. - virtual void Display(struct DisplayContext& dc) = 0; - - //! Mouse callback sent from viewport. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Return false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport that sent this callback. - //! @param event Indicate what kind of event occured in viewport. - //! @param point 2D coordinate in viewport where event occured. - //! @param flags Additional flags (MK_LBUTTON,etc..) or from (MouseEventFlags) specified by viewport when calling callback. - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) = 0; - - //! Called when key in viewport is pressed while using this tool. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Returns false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport where key was pressed. - //! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h - //! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key. - //! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN) - virtual bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - - //! Called when key in viewport is released while using this tool. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Returns false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport where key was pressed. - //! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h - //! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key. - //! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN) - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - - //! Called when mouse is moved and give oportunity to tool to set it own cursor. - //! @return true if cursor changed. or false otherwise. - virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; }; - - // Return objects affected by this edit tool. The returned objects usually will be the selected objects. - virtual void GetAffectedObjects(DynArray& outAffectedObjects); - - // Called in response to the dragging of the manipulator in the view. - // Allow edit tool to handle manipulator dragging the way it wants. - virtual void OnManipulatorDrag([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] QPoint& p0, [[maybe_unused]] QPoint& p1, [[maybe_unused]] const Vec3& value) {} - - virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, const Vec3& value) - { - // Overload with less boiler-plate - QPoint p0, p1; - OnManipulatorDrag(view, pManipulator, p0, p1, value); - } - - // Called in response to mouse event of the manipulator in the view - virtual void OnManipulatorMouseEvent([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags, [[maybe_unused]] bool bHitGizmo = false) {} - - virtual bool IsNeedMoveTool() { return false; } - virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return false; } - virtual bool IsNeedToSkipPivotBoxForObjects() { return false; } - virtual bool IsDisplayGrid() { return true; } - virtual bool IsUpdateUIPanel() { return false; } - virtual bool IsMoveToObjectModeAfterEnd() { return true; } - virtual bool IsCircleTypeRotateGizmo() { return false; } - - // Draws object specific helpers for this tool - virtual void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) {} - - // Hit test against edit tool - virtual bool HitTest([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] HitContext& hc) { return false; } - -protected: - virtual ~CEditTool() {}; - ////////////////////////////////////////////////////////////////////////// - // Delete edit tool. - ////////////////////////////////////////////////////////////////////////// - virtual void DeleteThis() = 0; - -protected: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - _smart_ptr m_pParentTool; // Pointer to parent edit tool. - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - QString m_statusText; - IClassDesc* m_pClassDesc; - int m_nRefCount; -}; - -#endif // CRYINCLUDE_EDITOR_EDITTOOL_H diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp index b10d564031..a7420b79a4 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp @@ -63,11 +63,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("DeepSelectionRange", &DeepSelection::m_deepSelectionRange) ->Field("StickDuplicate", &DeepSelection::m_stickDuplicate); - serialize.Class() - ->Version(1) - ->Field("VertexCubeSize", &VertexSnapping::m_vertexCubeSize) - ->Field("RenderPenetratedBoundBox", &VertexSnapping::m_bRenderPenetratedBoundBox); - serialize.Class() ->Version(1) ->Field("DynamicByDefault", &SliceSettings::m_slicesDynamicByDefault); @@ -78,7 +73,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) - ->Field("Vertex Snapping", &CEditorPreferencesPage_General::m_vertexSnapping) ->Field("Slice Settings", &CEditorPreferencesPage_General::m_sliceSettings); @@ -119,12 +113,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1000.0f); - editContext->Class("Vertex Snapping", "") - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &VertexSnapping::m_vertexCubeSize, "Vertex Cube Size", "Vertex Cube Size") - ->Attribute(AZ::Edit::Attributes::Min, 0.0001f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &VertexSnapping::m_bRenderPenetratedBoundBox, "Render Penetrated BoundBoxes", "Render Penetrated BoundBoxes"); - editContext->Class("Slices", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &SliceSettings::m_slicesDynamicByDefault, "New Slices Dynamic By Default", "When creating slices, they will be set to dynamic by default"); @@ -135,7 +123,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_vertexSnapping, "Vertex Snapping", "Vertex Snapping") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_sliceSettings, "Slices", "Slice Settings"); } } @@ -189,10 +176,6 @@ void CEditorPreferencesPage_General::OnApply() gSettings.deepSelectionSettings.fRange = m_deepSelection.m_deepSelectionRange; gSettings.deepSelectionSettings.bStickDuplicate = m_deepSelection.m_stickDuplicate; - //vertex snapping - gSettings.vertexSnappingSettings.vertexCubeSize = m_vertexSnapping.m_vertexCubeSize; - gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox = m_vertexSnapping.m_bRenderPenetratedBoundBox; - //slices gSettings.sliceSettings.dynamicByDefault = m_sliceSettings.m_slicesDynamicByDefault; @@ -236,10 +219,6 @@ void CEditorPreferencesPage_General::InitializeSettings() m_deepSelection.m_deepSelectionRange = gSettings.deepSelectionSettings.fRange; m_deepSelection.m_stickDuplicate = gSettings.deepSelectionSettings.bStickDuplicate; - //vertex snapping - m_vertexSnapping.m_vertexCubeSize = gSettings.vertexSnappingSettings.vertexCubeSize; - m_vertexSnapping.m_bRenderPenetratedBoundBox = gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox; - //slices m_sliceSettings.m_slicesDynamicByDefault = gSettings.sliceSettings.dynamicByDefault; } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h index d996f410a7..31776e9c10 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h @@ -88,14 +88,6 @@ private: bool m_stickDuplicate; }; - struct VertexSnapping - { - AZ_TYPE_INFO(VertexSnapping, "{20F16350-990C-4096-86E3-40D56DDDD702}") - - float m_vertexCubeSize; - bool m_bRenderPenetratedBoundBox; - }; - struct SliceSettings { AZ_TYPE_INFO(SliceSettings, "{8505CCC1-874C-4389-B51A-B9E5FF70CFDA}") @@ -107,7 +99,6 @@ private: Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; - VertexSnapping m_vertexSnapping; SliceSettings m_sliceSettings; QIcon m_icon; }; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 977850bc58..86fda8ceae 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -65,7 +65,6 @@ #include "Util/fastlib.h" #include "CryEditDoc.h" #include "GameEngine.h" -#include "EditTool.h" #include "ViewManager.h" #include "Objects/DisplayContext.h" #include "DisplaySettings.h" diff --git a/Code/Sandbox/Editor/GameExporter.cpp b/Code/Sandbox/Editor/GameExporter.cpp index 5173071024..00836018cf 100644 --- a/Code/Sandbox/Editor/GameExporter.cpp +++ b/Code/Sandbox/Editor/GameExporter.cpp @@ -125,9 +125,6 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE { QDir::setCurrent(pEditor->GetPrimaryCDFolder()); - // Close all Editor tools - pEditor->SetEditTool(0); - QString sLevelPath = Path::AddSlash(pGameEngine->GetLevelPath()); if (subdirectory && subdirectory[0] && strcmp(subdirectory, ".") != 0) { diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index 722f2a7c25..83a0029d9f 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -40,7 +40,6 @@ struct QMetaObject; class CBaseObject; class CCryEditDoc; class CSelectionGroup; -class CEditTool; class CAnimationContext; class CTrackViewSequenceManager; class CGameEngine; @@ -623,14 +622,6 @@ struct IEditor //! editMode - EEditMode virtual void SetEditMode(int editMode) = 0; virtual int GetEditMode() = 0; - //! Assign current edit tool, destroy previously used edit too. - virtual void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) = 0; - //! Assign current edit tool by class name. - virtual void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) = 0; - //! Reinitializes the current edit tool if one is selected. - virtual void ReinitializeEditTool() = 0; - //! Returns current edit tool. - virtual CEditTool* GetEditTool() = 0; //! Shows/Hides transformation manipulator. //! if bShow is true also returns a valid ITransformManipulator pointer. virtual ITransformManipulator* ShowTransformManipulator(bool bShow) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index 399ac45794..d4fd86312e 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -54,7 +54,6 @@ AZ_POP_DISABLE_WARNING #include "Export/ExportManager.h" #include "LevelIndependentFileMan.h" #include "Material/MaterialManager.h" -#include "Material/MaterialPickTool.h" #include "TrackView/TrackViewSequenceManager.h" #include "AnimationContext.h" #include "GameEngine.h" @@ -71,13 +70,9 @@ AZ_POP_DISABLE_WARNING #include "Objects/SelectionGroup.h" #include "Objects/ObjectManager.h" -#include "RotateTool.h" -#include "NullEditTool.h" - #include "BackgroundTaskManager.h" #include "BackgroundScheduleManager.h" #include "EditorFileMonitor.h" -#include "EditMode/VertexSnappingModeTool.h" #include "Mission.h" #include "MainStatusBar.h" @@ -451,12 +446,6 @@ void CEditorImpl::RegisterTools() rc.pCommandManager = m_pCommandManager; rc.pClassFactory = m_pClassFactory; - - CObjectMode::RegisterTool(rc); - CMaterialPickTool::RegisterTool(rc); - CVertexSnappingModeTool::RegisterTool(rc); - CRotateTool::RegisterTool(rc); - NullEditTool::RegisterTool(rc); } void CEditorImpl::ExecuteCommand(const char* sCommand, ...) @@ -682,14 +671,6 @@ void CEditorImpl::SetEditMode(int editMode) } } - if ((EEditMode)editMode == eEditModeRotate) - { - if (GetEditTool() && GetEditTool()->IsCircleTypeRotateGizmo()) - { - editMode = eEditModeRotateCircle; - } - } - EEditMode newEditMode = (EEditMode)editMode; if (m_currEditMode == newEditMode) { @@ -700,11 +681,6 @@ void CEditorImpl::SetEditMode(int editMode) AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0)); SetSelectedRegion(box); - if (GetEditTool() && !GetEditTool()->IsNeedMoveTool()) - { - SetEditTool(0, true); - } - Notify(eNotify_OnEditModeChange); } @@ -719,139 +695,6 @@ EOperationMode CEditorImpl::GetOperationMode() return m_operationMode; } -bool CEditorImpl::HasCorrectEditTool() const -{ - if (!m_pEditTool) - { - return false; - } - - switch (m_currEditMode) - { - case eEditModeRotate: - return qobject_cast(m_pEditTool) != nullptr; - default: - return qobject_cast(m_pEditTool) != nullptr && qobject_cast(m_pEditTool) == nullptr; - } -} - -CEditTool* CEditorImpl::CreateCorrectEditTool() -{ - if (m_currEditMode == eEditModeRotate) - { - CBaseObject* selectedObj = nullptr; - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection && pSelection->GetCount() > 0) - { - selectedObj = pSelection->GetObject(0); - } - - return (new CRotateTool(selectedObj)); - } - - return (new CObjectMode); -} - -void CEditorImpl::SetEditTool(CEditTool* tool, bool bStopCurrentTool) -{ - CViewport* pViewport = GetIEditor()->GetActiveView(); - if (pViewport) - { - pViewport->SetCurrentCursor(STD_CURSOR_DEFAULT); - } - - if (!tool) - { - if (HasCorrectEditTool()) - { - return; - } - else - { - tool = CreateCorrectEditTool(); - } - } - - if (!tool->Activate(m_pEditTool)) - { - return; - } - - if (bStopCurrentTool) - { - if (m_pEditTool && m_pEditTool != tool) - { - m_pEditTool->EndEditParams(); - SetStatusText("Ready"); - } - } - - m_pEditTool = tool; - if (m_pEditTool) - { - m_pEditTool->BeginEditParams(this, 0); - } - - Notify(eNotify_OnEditToolChange); -} - -void CEditorImpl::ReinitializeEditTool() -{ - if (m_pEditTool) - { - m_pEditTool->EndEditParams(); - m_pEditTool->BeginEditParams(this, 0); - } -} - -void CEditorImpl::SetEditTool(const QString& sEditToolName, [[maybe_unused]] bool bStopCurrentTool) -{ - CEditTool* pTool = GetEditTool(); - if (pTool && pTool->GetClassDesc()) - { - // Check if already selected. - if (QString::compare(pTool->GetClassDesc()->ClassName(), sEditToolName, Qt::CaseInsensitive) == 0) - { - return; - } - } - - IClassDesc* pClass = GetIEditor()->GetClassFactory()->FindClass(sEditToolName.toUtf8().data()); - if (!pClass) - { - Warning("Editor Tool %s not registered.", sEditToolName.toUtf8().data()); - return; - } - if (pClass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL) - { - Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data()); - return; - } - - QScopedPointer o(pClass->CreateQObject()); - if (CEditTool* pEditTool = qobject_cast(o.data())) - { - GetIEditor()->SetEditTool(pEditTool); - o.take(); - return; - } - else - { - Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data()); - return; - } -} - -CEditTool* CEditorImpl::GetEditTool() -{ - if (m_isNewViewportInteractionModelEnabled) - { - return nullptr; - } - - return m_pEditTool; -} - ITransformManipulator* CEditorImpl::ShowTransformManipulator(bool bShow) { if (bShow) diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index 4a8d5fa191..7bb864aaa3 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -229,18 +229,6 @@ public: void SetEditMode(int editMode); int GetEditMode(); - //! A correct tool is one that corresponds to the previously set edit mode. - bool HasCorrectEditTool() const; - - //! Returns the edit tool required for the edit mode specified. - CEditTool* CreateCorrectEditTool(); - - void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) override; - void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) override; - void ReinitializeEditTool() override; - //! Returns current edit tool. - CEditTool* GetEditTool() override; - ITransformManipulator* ShowTransformManipulator(bool bShow); ITransformManipulator* GetTransformManipulator(); void SetAxisConstraints(AxisConstrains axis); @@ -400,7 +388,6 @@ protected: CXmlTemplateRegistry m_templateRegistry; CDisplaySettings* m_pDisplaySettings; CShaderEnum* m_pShaderEnum; - _smart_ptr m_pEditTool; CIconManager* m_pIconManager; std::unique_ptr m_pGizmoParameters; QString m_primaryCDFolder; diff --git a/Code/Sandbox/Editor/Include/IObjectManager.h b/Code/Sandbox/Editor/Include/IObjectManager.h index 184a080870..bf1bb97db9 100644 --- a/Code/Sandbox/Editor/Include/IObjectManager.h +++ b/Code/Sandbox/Editor/Include/IObjectManager.h @@ -188,8 +188,6 @@ public: virtual void SetSelection(const QString& name) = 0; //! Removes one of named selections. virtual void RemoveSelection(const QString& name) = 0; - //! Checks for changes to the current selection and makes adjustments accordingly - virtual void CheckAndFixSelection() = 0; //! Delete all objects in current selection group. virtual void DeleteSelection() = 0; diff --git a/Code/Sandbox/Editor/InfoBar.cpp b/Code/Sandbox/Editor/InfoBar.cpp index 60c24fe84e..9e50e4ed3e 100644 --- a/Code/Sandbox/Editor/InfoBar.cpp +++ b/Code/Sandbox/Editor/InfoBar.cpp @@ -25,7 +25,6 @@ #include "Objects/SelectionGroup.h" #include "Include/IObjectManager.h" #include "MathConversion.h" -#include "EditTool.h" AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include @@ -58,7 +57,6 @@ CInfoBar::CInfoBar(QWidget* parent) m_prevEditMode = 0; m_bSelectionLocked = false; m_bSelectionChanged = false; - m_editTool = 0; m_bDragMode = false; m_prevMoveSpeed = 0; m_currValue = Vec3(-111, +222, -333); //this wasn't initialized. I don't know what a good value is @@ -251,28 +249,6 @@ void CInfoBar::OnVectorUpdate(bool followTerrain) ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); if (pManipulator) { - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - - if (pEditTool) - { - Vec3 diff = v - m_lastValue; - if (emode == eEditModeMove) - { - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - if (emode == eEditModeRotate) - { - diff = DEG2RAD(diff); - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - if (emode == eEditModeScale) - { - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - } return; } @@ -421,39 +397,22 @@ void CInfoBar::IdleUpdate() updateUI = true; } - if (GetIEditor()->GetEditTool() != m_editTool) - { - updateUI = true; - m_editTool = GetIEditor()->GetEditTool(); - } - QString str; - if (m_editTool) - { - str = m_editTool->GetStatusText(); - if (str != m_sLastText) - { - updateUI = true; - } - } - if (updateUI) { - if (!m_editTool) + if (m_numSelected == 0) { - if (m_numSelected == 0) - { - str = tr("None Selected"); - } - else if (m_numSelected == 1) - { - str = tr("1 Object Selected"); - } - else - { - str = tr("%1 Objects Selected").arg(m_numSelected); - } + str = tr("None Selected"); } + else if (m_numSelected == 1) + { + str = tr("1 Object Selected"); + } + else + { + str = tr("%1 Objects Selected").arg(m_numSelected); + } + ui->m_statusText->setText(str); m_sLastText = str; } diff --git a/Code/Sandbox/Editor/InfoBar.h b/Code/Sandbox/Editor/InfoBar.h index 6bf89099fe..aa0d0628a2 100644 --- a/Code/Sandbox/Editor/InfoBar.h +++ b/Code/Sandbox/Editor/InfoBar.h @@ -124,7 +124,6 @@ protected: bool m_bDragMode; QString m_sLastText; - CEditTool* m_editTool; Vec3 m_lastValue; Vec3 m_currValue; float m_oldMainVolume; diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index e48fb5fec1..a309a1a5f5 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -125,10 +125,6 @@ public: MOCK_METHOD0(GetOperationMode, EOperationMode()); MOCK_METHOD1(SetEditMode, void(int )); MOCK_METHOD0(GetEditMode, int()); - MOCK_METHOD2(SetEditTool, void(CEditTool*, bool)); - MOCK_METHOD2(SetEditTool, void(const QString&, bool)); - MOCK_METHOD0(ReinitializeEditTool, void()); - MOCK_METHOD0(GetEditTool, CEditTool* ()); MOCK_METHOD1(ShowTransformManipulator, ITransformManipulator* (bool)); MOCK_METHOD0(GetTransformManipulator, ITransformManipulator* ()); MOCK_METHOD1(SetAxisConstraints, void(AxisConstrains )); diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 6acd8cfc20..d7659c2512 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -60,7 +60,6 @@ AZ_POP_DISABLE_WARNING // Editor #include "Resource.h" -#include "EditTool.h" #include "Core/LevelEditorMenuHandler.h" #include "ShortcutDispatcher.h" #include "LayoutWnd.h" @@ -270,15 +269,6 @@ namespace return QtViewPaneManager::instance()->IsVisible(viewClassName); } - AZStd::string PyGetStatusText() - { - if (GetIEditor()->GetEditTool()) - { - return AZStd::string(GetIEditor()->GetEditTool()->GetStatusText().toUtf8().data()); - } - return AZStd::string(""); - } - AZStd::vector PyGetViewPaneNames() { const QtViewPanes panes = QtViewPaneManager::instance()->GetRegisteredPanes(); @@ -693,7 +683,6 @@ void MainWindow::closeEvent(QCloseEvent* event) } // Close all edit panels. GetIEditor()->ClearSelection(); - GetIEditor()->SetEditTool(0); GetIEditor()->GetObjectManager()->EndEditParams(); // force clean up of all deferred deletes, so that we don't have any issues with windows from plugins not being deleted yet @@ -1104,11 +1093,6 @@ void MainWindow::InitActions() .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected) .SetIcon(Style::icon("Align_to_grid")) .SetApplyHoverEffect(); - am->AddAction(ID_MODIFY_ALIGNOBJTOSURF, tr("Align object to surface (Hold CTRL)")).SetCheckable(true) - .SetToolTip(tr("Align object to surface (Hold CTRL)")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateAlignToVoxel) - .SetIcon(Style::icon("Align_object_to_surface")) - .SetApplyHoverEffect(); } am->AddAction(ID_SNAP_TO_GRID, tr("Snap to grid")) @@ -1459,10 +1443,6 @@ void MainWindow::InitActions() .SetIcon(QIcon(":/MainWindow/toolbars/object_toolbar-03.svg")) .SetApplyHoverEffect() .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected); - // vertex snapping not yet supported when the new Viewport Interaction Model is enabled - am->AddAction(ID_OBJECTMODIFY_VERTEXSNAPPING, tr("Vertex snapping")) - .SetIcon(Style::icon("Vertex_snapping")) - .SetApplyHoverEffect(); } // Misc Toolbar Actions @@ -1510,8 +1490,6 @@ void MainWindow::OnEscapeAction() { AzToolsFramework::EditorEvents::Bus::Broadcast( &AzToolsFramework::EditorEvents::OnEscape); - - CCryEditApp::instance()->OnEditEscape(); } } } @@ -2640,7 +2618,6 @@ namespace AzToolsFramework addLegacyGeneral(behaviorContext->Method("exit", PyExit, nullptr, "Exits the editor.")); addLegacyGeneral(behaviorContext->Method("exit_no_prompt", PyExitNoPrompt, nullptr, "Exits the editor without prompting to save first.")); addLegacyGeneral(behaviorContext->Method("report_test_result", PyReportTest, nullptr, "Report test information.")); - addLegacyGeneral(behaviorContext->Method("get_status_text", PyGetStatusText, nullptr, "Gets the status text from the Editor's current edit tool")); } } } diff --git a/Code/Sandbox/Editor/Material/MaterialPickTool.cpp b/Code/Sandbox/Editor/Material/MaterialPickTool.cpp deleted file mode 100644 index 38e3d0612d..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPickTool.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialPickTool.h" - -// Editor -#include "MaterialManager.h" -#include "SurfaceInfoPicker.h" -#include "Viewport.h" - - -#define RENDER_MESH_TEST_DISTANCE 0.2f - -static IClassDesc * s_ToolClass = NULL; - -////////////////////////////////////////////////////////////////////////// -CMaterialPickTool::CMaterialPickTool() -{ - m_pClassDesc = s_ToolClass; - m_statusText = tr("Left Click To Pick Material"); -} - -////////////////////////////////////////////////////////////////////////// -CMaterialPickTool::~CMaterialPickTool() -{ - SetMaterial(0); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialPickTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - if (event == eMouseLDown) - { - if (m_pMaterial) - { - CMaterial* pMtl = GetIEditor()->GetMaterialManager()->FromIMaterial(m_pMaterial); - if (pMtl) - { - GetIEditor()->GetMaterialManager()->SetHighlightedMaterial(0); - GetIEditor()->OpenMaterialLibrary(pMtl); - Abort(); - return true; - } - } - } - else if (event == eMouseMove) - { - return OnMouseMove(view, flags, point); - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::Display(DisplayContext& dc) -{ - QPoint mousePoint = QCursor::pos(); - - dc.view->ScreenToClient(mousePoint); - - Vec3 wp = dc.view->ViewToWorld(mousePoint); - - if (m_pMaterial) - { - float color[4] = {1, 1, 1, 1}; - dc.renderer->Draw2dLabel(mousePoint.x() + 12, mousePoint.y ()+ 8, 1.2f, color, false, "%s", m_displayString.toUtf8().data()); - } - - float fScreenScale = dc.view->GetScreenScaleFactor(m_HitInfo.vHitPos) * 0.06f; - - dc.DepthTestOff(); - dc.SetColor(ColorB(0, 0, 255, 255)); - if (!m_HitInfo.vHitNormal.IsZero()) - { - dc.DrawLine(m_HitInfo.vHitPos, m_HitInfo.vHitPos + m_HitInfo.vHitNormal * fScreenScale); - - Vec3 raySrc, rayDir; - dc.view->ViewToWorldRay(mousePoint, raySrc, rayDir); - - Matrix34 tm; - - Vec3 zAxis = m_HitInfo.vHitNormal; - Vec3 xAxis = rayDir.Cross(zAxis); - if (!xAxis.IsZero()) - { - xAxis.Normalize(); - Vec3 yAxis = xAxis.Cross(zAxis).GetNormalized(); - tm.SetFromVectors(xAxis, yAxis, zAxis, m_HitInfo.vHitPos); - - dc.PushMatrix(tm); - dc.DrawCircle(Vec3(0, 0, 0), 0.5f * fScreenScale); - dc.PopMatrix(); - } - } - dc.DepthTestOn(); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialPickTool::OnMouseMove(CViewport* view, [[maybe_unused]] UINT nFlags, const QPoint& point) -{ - view->SetCurrentCursor(STD_CURSOR_HIT, ""); - - _smart_ptr pNearestMaterial(NULL); - - m_Mouse2DPosition = point; - - CSurfaceInfoPicker surfacePicker; - int nPickObjectGroupFlag = CSurfaceInfoPicker::ePOG_All; - if (surfacePicker.Pick(point, pNearestMaterial, m_HitInfo, NULL, nPickObjectGroupFlag)) - { - SetMaterial(pNearestMaterial); - return true; - } - - SetMaterial(0); - return false; -} - -const GUID& CMaterialPickTool::GetClassID() -{ - // {FD20F6F2-7B87-4349-A5D4-7533538E357F} - static const GUID guid = { - 0xfd20f6f2, 0x7b87, 0x4349, { 0xa5, 0xd4, 0x75, 0x33, 0x53, 0x8e, 0x35, 0x7f } - }; - return guid; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(s_ToolClass = new CQtViewClass("EditTool.PickMaterial", "Material", ESYSTEM_CLASS_EDITTOOL)); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::SetMaterial(_smart_ptr pMaterial) -{ - if (pMaterial == m_pMaterial) - { - return; - } - - m_pMaterial = pMaterial; - CMaterial* pCMaterial = GetIEditor()->GetMaterialManager()->FromIMaterial(m_pMaterial); - GetIEditor()->GetMaterialManager()->SetHighlightedMaterial(pCMaterial); - - m_displayString = ""; - if (pMaterial) - { - QString sfType; - sfType = QStringLiteral("%1 : %2").arg(pMaterial->GetSurfaceType()->GetId()).arg(pMaterial->GetSurfaceType()->GetName()); - - m_displayString = "\n"; - m_displayString += pMaterial->GetName(); - m_displayString += "\n"; - m_displayString += sfType; - } -} - -#include diff --git a/Code/Sandbox/Editor/Material/MaterialPickTool.h b/Code/Sandbox/Editor/Material/MaterialPickTool.h deleted file mode 100644 index 09c5691315..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPickTool.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of PickObjectTool, tool used to pick objects. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H -#pragma once - -#include "EditTool.h" - -////////////////////////////////////////////////////////////////////////// -class CMaterialPickTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CMaterialPickTool(); - - static const GUID& GetClassID(); - - static void RegisterTool(CRegistrationContext& rc); - - ////////////////////////////////////////////////////////////////////////// - // CEditTool implementation - ////////////////////////////////////////////////////////////////////////// - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - virtual void Display(DisplayContext& dc); - ////////////////////////////////////////////////////////////////////////// - -protected: - - bool OnMouseMove(CViewport* view, UINT nFlags, const QPoint& point); - void SetMaterial(_smart_ptr pMaterial); - - virtual ~CMaterialPickTool(); - // Delete itself. - void DeleteThis() { delete this; }; - - _smart_ptr m_pMaterial; - QString m_displayString; - QPoint m_Mouse2DPosition; - SRayHitInfo m_HitInfo; -}; - - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H diff --git a/Code/Sandbox/Editor/NullEditTool.cpp b/Code/Sandbox/Editor/NullEditTool.cpp deleted file mode 100644 index b848ed6364..0000000000 --- a/Code/Sandbox/Editor/NullEditTool.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -#include "NullEditTool.h" - - -NullEditTool::NullEditTool() {} - -const GUID& NullEditTool::GetClassID() -{ - // {65AFF87A-34E0-479B-B062-94B1B867B13D} - static const GUID guid = - { - 0x65AFF87A, 0x34E0, 0x479B,{ 0xB0, 0x62, 0x94, 0xB1, 0xB8, 0x67, 0xB1, 0x3D } - }; - - return guid; -} - -void NullEditTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass( - new CQtViewClass("EditTool.NullEditTool", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -#include diff --git a/Code/Sandbox/Editor/NullEditTool.h b/Code/Sandbox/Editor/NullEditTool.h deleted file mode 100644 index 44bb4ce76d..0000000000 --- a/Code/Sandbox/Editor/NullEditTool.h +++ /dev/null @@ -1,39 +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 - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#endif - -/// An EditTool that does nothing - it provides the Null-Object pattern. -class SANDBOX_API NullEditTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE NullEditTool(); - virtual ~NullEditTool() = default; - - static const GUID& GetClassID(); - static void RegisterTool(CRegistrationContext& rc); - - // CEditTool - void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) override {} - void EndEditParams() override {} - void Display([[maybe_unused]] DisplayContext& dc) override {} - bool MouseCallback([[maybe_unused]] CViewport* view, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags) override { return false; } - bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) override { return false; } - bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) override { return true; } - void DeleteThis() override { delete this; } -}; \ No newline at end of file diff --git a/Code/Sandbox/Editor/ObjectCloneTool.cpp b/Code/Sandbox/Editor/ObjectCloneTool.cpp deleted file mode 100644 index fd8256f4cb..0000000000 --- a/Code/Sandbox/Editor/ObjectCloneTool.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "ObjectCloneTool.h" - -// Editor -#include "MainWindow.h" -#include "Viewport.h" -#include "ViewManager.h" -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" -#include "Settings.h" - -////////////////////////////////////////////////////////////////////////// -// Class description. -////////////////////////////////////////////////////////////////////////// -class CObjectCloneTool_ClassDesc - : public CRefCountClassDesc -{ - virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; } - virtual REFGUID ClassID() - { - // {6A73E865-71DF-4ED0-ABA2-457E66119B35} - static const GUID guid = { - 0x6a73e865, 0x71df, 0x4ed0,{ 0xab, 0xa2, 0x45, 0x7e, 0x66, 0x11, 0x9b, 0x35 } - }; - return guid; - } - virtual QString ClassName() { return "EditTool.Clone"; }; - virtual QString Category() { return "EditTool"; }; -}; -CObjectCloneTool_ClassDesc g_cloneClassDesc; - -////////////////////////////////////////////////////////////////////////// -CObjectCloneTool::CObjectCloneTool() - : m_currentUndoBatch(nullptr) -{ - m_pClassDesc = &g_cloneClassDesc; - m_bSetConstrPlane = true; - - GetIEditor()->SuperBeginUndo(); - - GetIEditor()->BeginUndo(); - m_selection = nullptr; - if (!GetIEditor()->GetSelection()->IsEmpty()) - { - QWaitCursor wait; - CloneSelection(); - m_selection = GetIEditor()->GetSelection(); - m_origin = m_selection->GetCenter(); - } - GetIEditor()->AcceptUndo("Clone"); - GetIEditor()->BeginUndo(); - - if (!gSettings.deepSelectionSettings.bStickDuplicate) - { - SetStatusText("Clone object at the same location"); - } - else - { - SetStatusText("Left click to clone object"); - } -} - -////////////////////////////////////////////////////////////////////////// -CObjectCloneTool::~CObjectCloneTool() -{ - EndUndoBatch(); - - if (GetIEditor()->IsUndoRecording()) - { - GetIEditor()->SuperCancelUndo(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::CloneSelection() -{ - // Allow component application to intercept cloning behavior. - // This is to allow support for "smart" cloning of prefabs, and other contextual features. - AZ_Assert(!m_currentUndoBatch, "CloneSelection undo batch already created."); - EBUS_EVENT_RESULT(m_currentUndoBatch, AzToolsFramework::ToolsApplicationRequests::Bus, BeginUndoBatch, "Clone Selection"); - bool handled = false; - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, CloneSelection, handled); - if (handled) - { - GetIEditor()->GetObjectManager()->CheckAndFixSelection(); - return; - } - - // This is the legacy case. We're not cloning AZ entities, so abandon the AZ undo batch. - EndUndoBatch(); - - CSelectionGroup selObjects; - CSelectionGroup sel; - - CSelectionGroup* currSelection = GetIEditor()->GetSelection(); - - currSelection->Clone(selObjects); - - GetIEditor()->ClearSelection(); - for (int i = 0; i < selObjects.GetCount(); i++) - { - if (selObjects.GetObject(i)) - { - GetIEditor()->SelectObject(selObjects.GetObject(i)); - } - } - MainWindow::instance()->setFocus(); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::SetConstrPlane(CViewport* view, [[maybe_unused]] const QPoint& point) -{ - Matrix34 originTM; - originTM.SetIdentity(); - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() == 1) - { - originTM = selection->GetObject(0)->GetWorldTM(); - } - else if (selection->GetCount() > 1) - { - originTM = selection->GetObject(0)->GetWorldTM(); - Vec3 center = view->SnapToGrid(originTM.GetTranslation()); - originTM.SetTranslation(center); - } - view->SetConstructionMatrix(COORDS_LOCAL, originTM); -} - -//static Vec3 gP1,gP2; -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Display([[maybe_unused]] DisplayContext& dc) -{ - //dc.SetColor( 1,1,0,1 ); - //dc.DrawBall( gP1,1.1f ); - //dc.DrawBall( gP2,1.1f ); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectCloneTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - if (m_selection) - { - // Set construction plane origin to selection origin. - if (m_bSetConstrPlane) - { - SetConstrPlane(view, point); - m_bSetConstrPlane = false; - } - - if (event == eMouseLDown) - { - // Accept group. - Accept(); - GetIEditor()->GetSelection()->FinishChanges(); - return true; - } - if (event == eMouseMove) - { - // Move selection. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection != m_selection) - { - Abort(); - } - else if (!selection->IsEmpty()) - { - GetIEditor()->RestoreUndo(); - - Vec3 v; - bool followTerrain = false; - - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - Vec3 selectionCenter = view->SnapToGrid(pSelection->GetCenter()); - - int axis = GetIEditor()->GetAxisConstrains(); - if (axis == AXIS_TERRAIN) - { - bool hitTerrain; - v = view->ViewToWorld(point, &hitTerrain) - selectionCenter; - if (axis == AXIS_TERRAIN) - { - v = view->SnapToGrid(v); - if (hitTerrain) - { - followTerrain = true; - v.z = 0; - } - } - } - else - { - Vec3 p1 = selectionCenter; - Vec3 p2 = view->MapViewToCP(point); - if (p2.IsZero()) - { - return true; - } - - v = view->GetCPVector(p1, p2); - // Snap v offset to grid if its enabled. - view->SnapToGrid(v); - } - - CSelectionGroup::EMoveSelectionFlag selectionFlag = CSelectionGroup::eMS_None; - if (followTerrain) - { - selectionFlag = CSelectionGroup::eMS_FollowTerrain; - } - - // Disable undo recording for these move commands as the only operation we need - // to undo is the creation of the new object. Undo commands are queued so it's - // possible that the object creation could be undone before attempting to undo - // these move operations causing undesired behavior. - bool wasRecording = CUndo::IsRecording(); - if (wasRecording) - { - GetIEditor()->SuspendUndo(); - } - - GetIEditor()->GetSelection()->Move(v, selectionFlag, GetIEditor()->GetReferenceCoordSys(), point); - - if (wasRecording) - { - GetIEditor()->ResumeUndo(); - } - } - } - if (event == eMouseWheel) - { - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection != m_selection) - { - Abort(); - } - else if (!selection->IsEmpty()) - { - double angle = 1; - - if (view->GetViewManager()->GetGrid()->IsAngleSnapEnabled()) - { - angle = view->GetViewManager()->GetGrid()->GetAngleSnap(); - } - - for (int i = 0; i < selection->GetCount(); ++i) - { - CBaseObject* pObj = selection->GetFilteredObject(i); - Quat rot = pObj->GetRotation(); - rot.SetRotationXYZ(Ang3(0, 0, rot.GetRotZ() + DEG2RAD(flags > 0 ? angle * (-1) : angle))); - pObj->SetRotation(rot); - } - GetIEditor()->AcceptUndo("Rotate Selection"); - } - } - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Abort() -{ - EndUndoBatch(); - - // Abort - GetIEditor()->SetEditTool(0); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Accept(bool resetPosition) -{ - // Close the az undo batch so it can add the appropriate objects to the cry undo stack - EndUndoBatch(); - - if (resetPosition) - { - GetIEditor()->GetSelection()->MoveTo(m_origin, CSelectionGroup::eMS_None, GetIEditor()->GetReferenceCoordSys()); - } - - if (GetIEditor()->IsUndoRecording()) - { - GetIEditor()->SuperAcceptUndo("Clone"); - } - - GetIEditor()->SetEditTool(0); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::EndUndoBatch() -{ - if (m_currentUndoBatch) - { - AzToolsFramework::UndoSystem::URSequencePoint* undoBatch = nullptr; - EBUS_EVENT_RESULT(undoBatch, AzToolsFramework::ToolsApplicationRequests::Bus, GetCurrentUndoBatch); - AZ_Error("ObjectCloneTool", undoBatch == m_currentUndoBatch, "Undo batch is not in sync."); - if (undoBatch == m_currentUndoBatch) - { - EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, EndUndoBatch); - } - m_currentUndoBatch = nullptr; - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::EndEditParams() -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectCloneTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - Abort(); - } - return false; -} - -#include diff --git a/Code/Sandbox/Editor/ObjectCloneTool.h b/Code/Sandbox/Editor/ObjectCloneTool.h deleted file mode 100644 index f027456a4e..0000000000 --- a/Code/Sandbox/Editor/ObjectCloneTool.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of ObjectCloneTool, edit tool for cloning of objects.. - - -#ifndef CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H -#define CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H - -#pragma once - -#include "EditTool.h" - -class CBaseObject; - -namespace AzToolsFramework -{ - namespace UndoSystem - { - class URSequencePoint; - } -} - -/*! - * CObjectCloneTool, When created duplicate current selection, and manages cloned selection. - * - */ - -class CObjectCloneTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CObjectCloneTool(); - - ////////////////////////////////////////////////////////////////////////// - // Ovverides from CEditTool - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - - virtual void BeginEditParams(IEditor* ie, int flags); - virtual void EndEditParams(); - - virtual void Display(DisplayContext& dc); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - ////////////////////////////////////////////////////////////////////////// - - void Accept(bool resetPosition = false); - void Abort(); - -protected: - virtual ~CObjectCloneTool(); - // Delete itself. - void DeleteThis() { delete this; }; - -private: - void CloneSelection(); - void SetConstrPlane(CViewport* view, const QPoint& point); - - CSelectionGroup* m_selection; - Vec3 m_origin; - bool m_bSetConstrPlane; - //bool m_bSetCapture; - - void EndUndoBatch(); - - AzToolsFramework::UndoSystem::URSequencePoint* m_currentUndoBatch; -}; - - -#endif // CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H diff --git a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp index 590b1256ac..44138b290d 100644 --- a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp +++ b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp @@ -24,7 +24,6 @@ #include "RenderHelpers/AxisHelper.h" #include "RenderHelpers/AxisHelperExtended.h" #include "IObjectManager.h" -#include "EditTool.h" ////////////////////////////////////////////////////////////////////////// // CAxisGizmo implementation. @@ -381,12 +380,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point break; } - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags); - } - return true; } } @@ -540,12 +533,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point break; } - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool && bCallBack) - { - pEditTool->OnManipulatorDrag(view, this, m_cMouseDownPos, point, vDragValue); - } - return true; } else @@ -573,12 +560,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point } bHit = true; } - - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags, bHit); - } } } else if (event == eMouseLUp) @@ -593,12 +574,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point { GetIEditor()->SetReferenceCoordSys(m_coordSysBackUp); } - - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags); - } } } diff --git a/Code/Sandbox/Editor/Objects/BaseObject.cpp b/Code/Sandbox/Editor/Objects/BaseObject.cpp index 36b954315e..a579f303a9 100644 --- a/Code/Sandbox/Editor/Objects/BaseObject.cpp +++ b/Code/Sandbox/Editor/Objects/BaseObject.cpp @@ -39,7 +39,6 @@ #include "ViewManager.h" #include "IEditorImpl.h" #include "GameEngine.h" -#include "EditTool.h" // To use the Andrew's algorithm in order to make convex hull from the points, this header is needed. #include "Util/GeometryUtil.h" @@ -3264,11 +3263,6 @@ ERotationWarningLevel CBaseObject::GetRotationWarningLevel() const bool CBaseObject::IsSkipSelectionHelper() const { - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedToSkipPivotBoxForObjects()) - { - return true; - } return false; } diff --git a/Code/Sandbox/Editor/Objects/ObjectManager.cpp b/Code/Sandbox/Editor/Objects/ObjectManager.cpp index aff6d51816..96d015e2c1 100644 --- a/Code/Sandbox/Editor/Objects/ObjectManager.cpp +++ b/Code/Sandbox/Editor/Objects/ObjectManager.cpp @@ -22,12 +22,10 @@ #include "Settings.h" #include "DisplaySettings.h" #include "EntityObject.h" -#include "NullEditTool.h" #include "Viewport.h" #include "GizmoManager.h" #include "AxisGizmo.h" #include "ObjectPhysicsManager.h" -#include "EditMode/ObjectMode.h" #include "GameEngine.h" #include "WaitProgress.h" #include "Util/Image.h" @@ -838,8 +836,6 @@ void CObjectManager::Update() QWidget* prevActiveWindow = QApplication::activeWindow(); - CheckAndFixSelection(); - // Restore focus if it changed. if (prevActiveWindow && QApplication::activeWindow() != prevActiveWindow) { @@ -1230,60 +1226,6 @@ void CObjectManager::RemoveSelection(const QString& name) } } -//! Checks the state of the current selection and fixes it if necessary - Used when AZ Code modifies the selection -void CObjectManager::CheckAndFixSelection() -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - bool bObjectMode = qobject_cast(GetIEditor()->GetEditTool()) != nullptr; - - if (m_currSelection->GetCount() == 0) - { - // Nothing selected. - EndEditParams(); - if (bObjectMode) - { - GetIEditor()->ShowTransformManipulator(false); - } - } - else if (m_currSelection->GetCount() == 1) - { - if (!m_bSingleSelection) - { - EndEditParams(); - } - - CBaseObject* newSelObject = m_currSelection->GetObject(0); - // Single object selected. - if (m_currEditObject != m_currSelection->GetObject(0)) - { - m_bSelectionChanged = false; - if (!m_currEditObject || (m_currEditObject->metaObject() != newSelObject->metaObject())) - { - // If old object and new objects are of different classes. - EndEditParams(); - } - if (GetIEditor()->GetEditTool() && GetIEditor()->GetEditTool()->IsUpdateUIPanel()) - { - BeginEditParams(newSelObject, OBJECT_EDIT); - } - - //AfxGetMainWnd()->SetFocus(); - } - } - else if (m_currSelection->GetCount() > 1) - { - // Multiple objects are selected. - if (m_bSelectionChanged && bObjectMode) - { - m_bSelectionChanged = false; - m_nLastSelCount = m_currSelection->GetCount(); - EndEditParams(); - - m_currEditObject = m_currSelection->GetObject(0); - } - } -} - void CObjectManager::SelectCurrent() { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); @@ -1404,8 +1346,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) pDispayedViewObjects->ClearObjects(); pDispayedViewObjects->Reserve(m_visibleObjects.size()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - const bool newViewportInteractionModelEnabled = GetIEditor()->IsNewViewportInteractionModelEnabled(); if (dc.flags & DISPLAY_2D) @@ -1426,11 +1366,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) { obj->Display(dc); } - - if (pEditTool) - { - pEditTool->DrawObjectHelpers(obj, dc); - } } } } @@ -1476,11 +1411,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) { obj->Display(dc); } - - if (pEditTool) - { - pEditTool->DrawObjectHelpers(obj, dc); - } } } } @@ -1737,12 +1667,6 @@ bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc) { return false; } - - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (pEditTool && pEditTool->HitTest(obj, hc)) - { - return true; - } } return (bSelectionHelperHit || obj->HitTest(hc)); @@ -2742,10 +2666,6 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC void CObjectManager::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/) { - // provide an EditTool that does nothing. - // note: will hide rotation gizmo when active (CRotateTool) - GetIEditor()->SetEditTool(new NullEditTool()); - // hide current gizmo for entity (translate/rotate/scale) IGizmoManager* gizmoManager = GetGizmoManager(); const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount()); @@ -2757,9 +2677,6 @@ void CObjectManager::EnteredComponentMode(const AZStd::vector& /*compo void CObjectManager::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/) { - // return to default EditTool (in whatever transform mode is set) - GetIEditor()->SetEditTool(nullptr); - // show translate/rotate/scale gizmo again if (IGizmoManager* gizmoManager = GetGizmoManager()) { diff --git a/Code/Sandbox/Editor/Objects/ObjectManager.h b/Code/Sandbox/Editor/Objects/ObjectManager.h index eca23bc92b..f13616451e 100644 --- a/Code/Sandbox/Editor/Objects/ObjectManager.h +++ b/Code/Sandbox/Editor/Objects/ObjectManager.h @@ -226,8 +226,6 @@ public: //! Set one of name selections as current selection. void SetSelection(const QString& name); void RemoveSelection(const QString& name); - //! Checks for changes to the current selection and makes adjustments accordingly - void CheckAndFixSelection() override; bool IsObjectDeletionAllowed(CBaseObject* pObject); diff --git a/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl b/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl index fa56a21a8b..a6ceaf578f 100644 --- a/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl +++ b/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl @@ -17,7 +17,6 @@ #include "Include/IDisplayViewport.h" #include "Include/HitContext.h" #include "Util/Math.h" -#include "EditTool.h" #include "IObjectManager.h" #include diff --git a/Code/Sandbox/Editor/RenderViewport.cpp b/Code/Sandbox/Editor/RenderViewport.cpp index 213a4ed895..53355f4dd9 100644 --- a/Code/Sandbox/Editor/RenderViewport.cpp +++ b/Code/Sandbox/Editor/RenderViewport.cpp @@ -66,7 +66,6 @@ #include "Util/fastlib.h" #include "CryEditDoc.h" #include "GameEngine.h" -#include "EditTool.h" #include "ViewManager.h" #include "Objects/DisplayContext.h" #include "DisplaySettings.h" @@ -1948,12 +1947,6 @@ void CRenderViewport::RenderAll() m_entityVisibilityQuery.DisplayVisibility(*debugDisplay); - if (GetEditTool()) - { - // display editing tool - GetEditTool()->Display(displayContext); - } - if (m_manipulatorManager != nullptr) { using namespace AzToolsFramework::ViewportInteraction; @@ -2776,35 +2769,6 @@ void CRenderViewport::OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta handled = result != MouseInteractionResult::None; } - else - { - if (m_manipulatorManager == nullptr || m_manipulatorManager->ConsumeViewportMouseWheel(mouseInteraction)) - { - return; - } - - if (AzToolsFramework::ComponentModeFramework::InComponentMode()) - { - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::EventResult( - handled, AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, - MouseInteractionEvent(mouseInteraction, zDelta)); - } - else - { - ////////////////////////////////////////////////////////////////////////// - // Asks current edit tool to handle mouse callback. - CEditTool* pEditTool = GetEditTool(); - if (pEditTool && (modifiers & Qt::ControlModifier)) - { - QPoint tempPoint(scaledPoint.x(), scaledPoint.y()); - if (pEditTool->MouseCallback(this, eMouseWheel, tempPoint, zDelta)) - { - handled = true; - } - } - } - } if (!handled) { @@ -4347,10 +4311,6 @@ void CRenderViewport::RenderSnappingGrid() { return; } - if (GetIEditor()->GetEditTool() && !GetIEditor()->GetEditTool()->IsDisplayGrid()) - { - return; - } DisplayContext& dc = m_displayContext; diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index afcd0c7a6f..d72c2d76d4 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -123,7 +123,6 @@ #define ID_TOOL_SHELVE_LAST 33375 #define ID_EDIT_SELECTALL 33376 #define ID_EDIT_SELECTNONE 33377 -#define ID_OBJECTMODIFY_VERTEXSNAPPING 33384 #define ID_WIREFRAME 33410 #define ID_FILE_GENERATETERRAINTEXTURE 33445 #define ID_GENERATORS_LIGHTING 33446 @@ -275,7 +274,6 @@ #define ID_GAME_PC_ENABLEMEDIUMSPEC 33961 #define ID_GAME_PC_ENABLEHIGHSPEC 33962 #define ID_GAME_PC_ENABLEVERYHIGHSPEC 33963 -#define ID_MODIFY_ALIGNOBJTOSURF 33968 #define ID_PANEL_VEG_CREATE_SEL 33990 #define ID_TOOLS_UPDATEPROCEDURALVEGETATION 33999 #define ID_DISPLAY_GOTOPOSITION 34004 diff --git a/Code/Sandbox/Editor/RotateTool.cpp b/Code/Sandbox/Editor/RotateTool.cpp deleted file mode 100644 index e9b12d01af..0000000000 --- a/Code/Sandbox/Editor/RotateTool.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "EditorDefs.h" - -#include "RotateTool.h" - -// AzToolsFramework -#include - -// Editor -#include "Objects/SelectionGroup.h" -#include "NullEditTool.h" -#include "Viewport.h" -#include "Grid.h" -#include "ViewManager.h" -#include "Objects/BaseObject.h" - - -// This constant is used with GetScreenScaleFactor and was found experimentally. -static const float kViewDistanceScaleFactor = 0.06f; - -const GUID& CRotateTool::GetClassID() -{ - // {A50E5B95-05B9-41A3-8D8E-BDA3E930A396} - static const GUID guid = { - 0xA50E5B95, 0x05B9, 0x41A3, { 0x8D, 0x8E, 0xBD, 0xA3, 0xE9, 0x30, 0xA3, 0x96 } - }; - return guid; -} - -//! This method returns the human readable name of the class. -//! This method returns Category of this class, Category is specifying where this tool class fits best in create panel. -void CRotateTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass("EditTool.Rotate", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -CRotateTool::CRotateTool(CBaseObject* pObject, QWidget* parent /*= nullptr*/) - : CObjectMode(parent) - , m_initialViewAxisAngleRadians(0.f) - , m_angleToCursor(0.f) - , m_highlightAxis(AxisNone) - , m_draggingMouse(false) - , m_lastPosition(0, 0) - , m_rotationAngles(0, 0, 0) - , m_object(pObject) - , m_bTransformChanged(false) - , m_totalRotationAngle(0.f) - , m_basisAxisRadius(4.f) - , m_viewAxisRadius(5.f) - , m_arcRotationStepRadians(DEG2RAD(5.f)) -{ - m_axes[AxisX] = RotationDrawHelper::Axis(Col_Red, Col_Yellow); - m_axes[AxisY] = RotationDrawHelper::Axis(Col_Green, Col_Yellow); - m_axes[AxisZ] = RotationDrawHelper::Axis(Col_Blue, Col_Yellow); - m_axes[AxisView] = RotationDrawHelper::Axis(Col_White, Col_Yellow); - - if (m_object) - { - m_object->AddEventListener(this); - } - - GetIEditor()->GetObjectManager()->SetSelectCallback(this); -} - -bool CRotateTool::OnSelectObject(CBaseObject* object) -{ - m_object = object; - if (m_object) - { - m_object->AddEventListener(this); - } - return true; -} - -bool CRotateTool::CanSelectObject([[maybe_unused]] CBaseObject* object) -{ - return true; -} - -void CRotateTool::OnObjectEvent(CBaseObject* object, int event) -{ - if (event == CBaseObject::ON_DELETE || event == CBaseObject::ON_UNSELECT) - { - if (m_object && m_object == object) - { - m_object->RemoveEventListener(this); - m_object = nullptr; - } - } -} - -void CRotateTool::Display(DisplayContext& dc) -{ - if (!m_object) - { - return; - } - - const bool visible = - !m_object->IsHidden() - && !m_object->IsFrozen() - && m_object->IsSelected(); - - if (!visible) - { - GetIEditor()->SetEditTool(new NullEditTool()); - return; - } - - RotationDrawHelper::DisplayContextScope displayContextScope(dc); - m_hc.camera = dc.camera; - m_hc.view = dc.view; - m_hc.b2DViewport = static_cast(dc.view)->GetType() != ET_ViewportCamera; - dc.SetLineWidth(m_lineThickness); - - // Calculate the screen space position from which we cast a ray (center of viewport). - int viewportWidth = 0; - int viewportHeight = 0; - dc.view->GetDimensions(&viewportWidth, &viewportHeight); - m_hc.point2d = QPoint(viewportWidth / 2, viewportHeight / 2); - - // Calculate the ray from the camera position to the selection. - dc.view->ViewToWorldRay(m_hc.point2d, m_hc.raySrc, m_hc.rayDir); - - Matrix34 objectTransform = GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view); - - AffineParts ap; - ap.Decompose(objectTransform); - - Vec3 position = ap.pos; - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - // X axis arc - Vec3 cameraViewDir = (m_hc.raySrc - position).GetNormalized(); - float cameraAngle = atan2f(cameraViewDir.y, cameraViewDir.x); - m_axes[AxisX].Draw(dc, position, ap.rot.GetColumn0(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisX, m_object, screenScale); - - // Y axis arc - cameraAngle = atan2f(-cameraViewDir.z, cameraViewDir.x); - m_axes[AxisY].Draw(dc, position, ap.rot.GetColumn1(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisY, m_object, screenScale); - - // View direction axis - Vec3 cameraPos = dc.camera->GetPosition(); - - Vec3 axis = cameraPos - position; - axis.NormalizeSafe(); - - // Z axis arc - cameraAngle = atan2f(axis.y, axis.x); - m_axes[AxisZ].Draw(dc, position, objectTransform.GetColumn2().GetNormalized(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisZ, m_object, screenScale); - - // FIXME: currently, rotating multiple selections using the view axis may result in severe rotation artifacts, it's necessary to make sure - // the calculated rotation angle is smooth. - if (!m_hc.b2DViewport && selection->GetCount() == 1 || m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - // Draw view direction axis - dc.SetColor(m_highlightAxis == AxisView ? Col_Yellow : Col_White); - - cameraViewDir = m_hc.camera->GetViewdir().normalized(); - dc.DrawArc(position, m_viewAxisRadius * GetScreenScale(dc.view, dc.camera), 0, 360.f, RAD2DEG(m_arcRotationStepRadians), cameraViewDir); - } - - // Draw angle decorator - if (RotationControlConfiguration::Get().RotationControl_DrawDecorators) - { - DrawAngleDecorator(dc); - } - - // Display total rotation angle in degrees. - if (!m_hc.b2DViewport && fabs(m_totalRotationAngle) > FLT_EPSILON) - { - QString label; - label = QString::number(RAD2DEG(m_totalRotationAngle), 'f', 2); - - const float textScale = 1.5f; - const ColorF textBackground = ColorF(0.2f, 0.2f, 0.2f, 0.6f); - - if (m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - dc.DrawTextLabel(ap.pos, textScale, label.toUtf8().data()); - } - else - { - dc.DrawTextOn2DBox(ap.pos, label.toUtf8().data(), textScale, Col_White, textBackground); - } - } - - // Draw debug diagnostics - if (RotationControlConfiguration::Get().RotationControl_DebugHitTesting) - { - DrawHitTestGeometry(dc, m_hc); - } - - // Draw debug tracking of the view direction angle - if (RotationControlConfiguration::Get().RotationControl_AngleTracking) - { - DrawViewDirectionAngleTracking(dc, m_hc); - } -} - -void CRotateTool::DrawAngleDecorator(DisplayContext& dc) -{ - if (m_highlightAxis == AxisView) - { - //Vec3 cameraViewDir = dc.view->GetViewTM().GetColumn1().GetNormalized(); - Vec3 cameraViewDir = dc.camera->GetViewMatrix().GetColumn1().GetNormalized(); //Get the viewDir from the camera instead of from the view - // FIXME: The angle and sweep calculation here is incorrect. - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - float angleDelta = (m_angleToCursor - g_PI2 * floor(m_initialViewAxisAngleRadians / g_PI2)) - (m_initialViewAxisAngleRadians - (cameraAngle - (g_PI / 2))); - - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), cameraViewDir, m_initialViewAxisAngleRadians, angleDelta, m_arcRotationStepRadians, m_viewAxisRadius, GetScreenScale(dc.view, dc.camera)); - } - else - { - if (fabs(m_totalRotationAngle) > FLT_EPSILON) - { - float screenScale = GetScreenScale(dc.view, dc.camera); - switch (m_highlightAxis) - { - case AxisX: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn0(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - case AxisY: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn1(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - case AxisZ: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn2(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - default: - break; - } - } - } -} - -bool CRotateTool::HitTest(CBaseObject* object, HitContext& hc) -{ - if (!m_object) - { - return CObjectMode::HitTest(object, hc); - } - m_hc = hc; - m_highlightAxis = AxisNone; - - float screenScale = GetScreenScale(hc.view, hc.camera); - - // Determine intersection with the axis view direction. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (!m_hc.b2DViewport && selection->GetCount() == 1 || m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - if (m_axes[AxisView].HitTest(object, hc, m_viewAxisRadius, m_arcRotationStepRadians, hc.camera ? hc.camera->GetViewMatrix().GetInverted().GetColumn1() : hc.view->GetViewTM().GetColumn1(), screenScale)) - { - m_highlightAxis = AxisView; - GetIEditor()->SetAxisConstraints(AXIS_XYZ); - return true; - } - } - - // Determine any intersection with a major axis. - AffineParts ap; - ap.Decompose(GetTransform(GetIEditor()->GetReferenceCoordSys(), hc.view)); - - if (m_axes[AxisX].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn0(), screenScale)) - { - m_highlightAxis = AxisX; - GetIEditor()->SetAxisConstraints(AXIS_X); - return true; - } - - if (m_axes[AxisY].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn1(), screenScale)) - { - m_highlightAxis = AxisY; - GetIEditor()->SetAxisConstraints(AXIS_Y); - return true; - } - - if (m_axes[AxisZ].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn2(), screenScale)) - { - m_highlightAxis = AxisZ; - GetIEditor()->SetAxisConstraints(AXIS_Z); - return true; - } - - return false; -} - -void CRotateTool::DeleteThis() -{ - delete this; -} - -bool CRotateTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->GetObjectManager()->ClearSelection(); - return true; - } - return false; -} - -Matrix34 CRotateTool::GetTransform(RefCoordSys referenceCoordinateSystem, IDisplayViewport* view) -{ - Matrix34 objectTransform = Matrix34::CreateIdentity(); - if (m_object) - { - switch (referenceCoordinateSystem) - { - case COORDS_VIEW: - if (view) - { - objectTransform = view->GetViewTM(); - } - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - break; - case COORDS_LOCAL: - objectTransform = m_object->GetWorldTM(); - break; - case COORDS_PARENT: - if (m_object->GetParent()) - { - Matrix34 parentTM = m_object->GetParent()->GetWorldTM(); - parentTM.SetTranslation(m_object->GetWorldTM().GetTranslation()); - objectTransform = parentTM; - } - else - { - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - } - break; - case COORDS_WORLD: - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - break; - } - } - return objectTransform; -} - -float CRotateTool::CalculateOrientation(const QPoint& p1, const QPoint& p2, const QPoint& p3) -{ - // Source: https://www.geeksforgeeks.org/orientation-3-ordered-points/ - float c = (p2.y() - p1.y()) * (p3.x() - p2.x()) - (p3.y() - p2.y()) * (p2.x() - p1.x()); - return c > 0 ? 1.0f : -1.0f; -} - -CRotateTool::~CRotateTool() -{ - if (m_object) - { - m_object->RemoveEventListener(this); - } - GetIEditor()->GetObjectManager()->SetSelectCallback(nullptr); -} - -bool CRotateTool::OnLButtonDown(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - m_hc.view = view; - m_hc.b2DViewport = view->GetType() != ET_ViewportCamera; - m_hc.point2d = point; - if (nFlags == OBJFLAG_IS_PARTICLE) - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - - if (m_hc.object && m_hc.object != m_object) - { - GetIEditor()->ClearSelection(); - return CObjectMode::OnLButtonDown(view, nFlags, point); - } - - if (m_highlightAxis != AxisNone) - { - view->BeginUndo(); - view->CaptureMouse(); - view->SetCurrentCursor(STD_CURSOR_ROTATE); - - m_draggingMouse = true; - - // Store the starting drag angle when we first click the mouse, we will need this to know - // how much of the rotation we need to apply. - if (m_highlightAxis == AxisView) - { - Vec3 cameraViewDir = m_hc.camera->GetViewdir().GetNormalized(); - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - m_initialViewAxisAngleRadians = m_angleToCursor - cameraAngle - (g_PI / 2); - m_initialViewAxisAngleRadians -= static_cast(g_PI); - } - - m_lastPosition = point; - m_rotationAngles = Ang3(0, 0, 0); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanging, - selectedEntities); - - return true; - } - - return CObjectMode::OnLButtonDown(view, nFlags, point); -} - -bool CRotateTool::OnLButtonUp(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - if (nFlags == OBJFLAG_IS_PARTICLE) - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - - if (m_draggingMouse) - { - // We are no longer dragging the mouse, so we will release it and reset any state variables. - { - AzToolsFramework::ScopedUndoBatch undo("Rotate"); - } - view->AcceptUndo("Rotate Selection"); - view->ReleaseMouse(); - view->SetCurrentCursor(STD_CURSOR_DEFAULT); - - m_draggingMouse = false; - m_totalRotationAngle = 0.f; - m_initialViewAxisAngleRadians = 0.f; - m_angleToCursor = 0.f; - - // Apply the transform changes to the selection. - if (m_bTransformChanged) - { - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - if (pSelection) - { - pSelection->FinishChanges(); - } - - m_bTransformChanged = false; - - view->ResetSelectionRegion(); - // Reset selected rectangle. - view->SetSelectionRectangle(QRect()); - view->SetAxisConstrain(GetIEditor()->GetAxisConstrains()); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, - selectedEntities); - } - } - - return CObjectMode::OnLButtonUp(view, nFlags, point); -} - -bool CRotateTool::OnMouseMove(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - if (!m_object) - { - return CObjectMode::OnMouseMove(view, nFlags, point); - } - - // Prevent the opening of the context menu during a mouse move. - m_openContext = false; - - // We calculate the mouse drag direction vector's angle from the object to the mouse position. - QPoint objectCenter; - if (nFlags != OBJFLAG_IS_PARTICLE) - { - objectCenter = view->WorldToView(GetIEditor()->GetSelection()->GetCenter()); - } - else - if (parent() && parent()->isWidgetType()) - { - QWidget *wParent = static_cast(parent()); - - // HACK: This is only valid for the particle editor and needs refactored. - const QRect rect = wParent->contentsRect(); - objectCenter = view->WorldToViewParticleEditor(m_object->GetWorldPos(), rect.width(), rect.height()); - } - - Vec2 dragDirection = Vec2(point.x() - objectCenter.x(), point.y() - objectCenter.y()); - dragDirection.Normalize(); - - float angleToCursor = (atan2f(dragDirection.y, dragDirection.x)); - m_angleToCursor = angleToCursor - g_PI2 * floor(angleToCursor / g_PI2); - - if (m_draggingMouse) - { - GetIEditor()->RestoreUndo(); - - view->SetCurrentCursor(STD_CURSOR_ROTATE); - - RefCoordSys referenceCoordSys = GetIEditor()->GetReferenceCoordSys(); - - if (m_highlightAxis == AxisView) - { - // Calculate the angular difference between the starting rotation angle, taking into account the camera's angle to ensure a smooth rotation. - Vec3 cameraViewDir = m_hc.camera->GetViewdir(); - float cameraAngle = atan2f(cameraViewDir.y, cameraViewDir.x); - float angleDelta = (m_angleToCursor - g_PI2 * floor(m_initialViewAxisAngleRadians / g_PI2)) - (m_initialViewAxisAngleRadians - (cameraAngle - (g_PI / 2))); - - // Snap the angle is necessary - angleDelta = view->GetViewManager()->GetGrid()->SnapAngle(RAD2DEG(angleDelta)); - - if (nFlags != OBJFLAG_IS_PARTICLE) - { - Matrix34 viewRotation = Matrix34::CreateRotationAA(DEG2RAD(angleDelta), cameraViewDir); - GetIEditor()->GetSelection()->Rotate(viewRotation, COORDS_WORLD); - } - else - { - Quat quatRotation = Quat::CreateRotationAA(DEG2RAD(angleDelta), cameraViewDir); - m_object->SetRotation(quatRotation); - } - - m_bTransformChanged = true; - } - else - if (m_highlightAxis != AxisNone) - { - float distanceMoved = (point - m_lastPosition).manhattanLength(); // screen-space distance dragged - float distanceToCenter = (m_lastPosition - objectCenter).manhattanLength(); // screen-space distance to object center - float roationDelta = RAD2DEG(atan2f(distanceMoved, distanceToCenter)); // unsigned rotation angle - float orientation = CalculateOrientation(objectCenter, m_lastPosition, point); // Calculate if rotation dragging gizmo clockwise or counter-clockwise - - m_lastPosition = point; - - // Calculate orientation of the object's axis towards camera - Vec3 directionToObject = (GetIEditor()->GetSelection()->GetCenter() - m_hc.camera->GetMatrix().GetTranslation()).normalize(); - - float directionX = 1.0f; - float directionY = 1.0f; - float directionZ = 1.0f; - - switch (referenceCoordSys) - { - case COORDS_LOCAL: - directionX = directionToObject.Dot(m_object->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - break; - case COORDS_PARENT: - if (m_object->GetParent()) - { - directionX = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - } - else - { - directionX = directionToObject.Dot(m_object->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - } - break; - case COORDS_VIEW: - case COORDS_WORLD: - directionX = directionToObject.Dot(Vec3(1, 0, 0)) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(Vec3(0, 1, 0)) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(Vec3(0, 0, 1)) > 0 ? -1.0f : 1.0f; - break; - } - - switch (m_highlightAxis) - { - case AxisX: - m_rotationAngles.x += roationDelta * directionX * orientation; - break; - case AxisY: - m_rotationAngles.y += roationDelta * directionY * orientation; - break; - case AxisZ: - m_rotationAngles.z += roationDelta * directionZ * orientation; - break; - default: - break; - } - - // Snap the angle if necessary - m_rotationAngles = view->GetViewManager()->GetGrid()->SnapAngle(m_rotationAngles); - - // Compute the total amount rotated - Vec3 vDragValue = Vec3(m_rotationAngles); - m_totalRotationAngle = DEG2RAD(vDragValue.len()); - - // Apply the rotation - if (nFlags != OBJFLAG_IS_PARTICLE) - { - GetIEditor()->GetSelection()->Rotate(m_rotationAngles, referenceCoordSys); - } - else - { - Quat currentRotation = (m_object->GetRotation()); - Quat rotateTM = currentRotation * Quat::CreateRotationXYZ(DEG2RAD(-m_rotationAngles / 50.0f)); - m_object->SetRotation(rotateTM); - } - - m_bTransformChanged = fabs(m_totalRotationAngle) > FLT_EPSILON; - } - } - else - { - // If we are not yet dragging the mouse, do the hit testing to highlight the axis the mouse is over. - m_hc.view = view; - m_hc.b2DViewport = view->GetType() != ET_ViewportCamera; - m_hc.point2d = point; - - if (nFlags != OBJFLAG_IS_PARTICLE) - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - - if (HitTest(m_object, m_hc)) - { - // Display a cursor that makes it clear to the user that he is over an axis that can be rotated. - view->SetCurrentCursor(STD_CURSOR_ROTATE); - } - else - { - // Nothing has been hit, reset the cursor back to default in case it was changed previously. - view->SetCurrentCursor(STD_CURSOR_DEFAULT); - } - } - - // We always consider the rotation tool's OnMove event handled - return true; -} - -float CRotateTool::GetScreenScale(IDisplayViewport* view, CCamera* camera /*=nullptr*/) -{ - Matrix34 objectTransform = GetTransform(GetIEditor()->GetReferenceCoordSys(), view); - - AffineParts ap; - ap.Decompose(objectTransform); - - if (m_object && m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - return view->GetScreenScaleFactor(*camera, ap.pos) * kViewDistanceScaleFactor; - } - - return static_cast(view)->GetScreenScaleFactor(ap.pos) * kViewDistanceScaleFactor; -} - -void CRotateTool::DrawHitTestGeometry(DisplayContext& dc, HitContext& hc) -{ - AffineParts ap; - ap.Decompose(GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view)); - - Vec3 position = ap.pos; - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - // Draw debug test surface for each axis. - m_axes[AxisX].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn0(), screenScale); - m_axes[AxisY].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn1(), screenScale); - m_axes[AxisZ].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn2(), screenScale); - - // We don't render the view axis rotation for multiple selection. - if (!hc.b2DViewport && selection->GetCount() == 1) - { - Vec3 cameraViewDir = hc.view->GetViewTM().GetColumn1().GetNormalized(); - m_axes[AxisView].DebugDrawHitTestSurface(dc, hc, position, m_viewAxisRadius, m_arcRotationStepRadians, cameraViewDir, screenScale); - } -} - -void CRotateTool::DrawViewDirectionAngleTracking(DisplayContext& dc, HitContext& hc) -{ - Vec3 a; - Vec3 b; - - // Calculate a basis for the camera view direction. - Vec3 cameraViewDir = hc.view->GetViewTM().GetColumn1().GetNormalized(); - GetBasisVectors(cameraViewDir, a, b); - - // Calculates the camera view direction angle. - float angle = m_angleToCursor; - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - - // Ensures the angle remains camera aligned. - angle -= cameraAngle - (g_PI / 2); - - // The position will be either the object's center or the selection's center. - Vec3 position = GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view).GetTranslation(); - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - const float cosAngle = cos(angle); - const float sinAngle = sin(angle); - - // The resulting position will be in a circular orientation based on the resulting angle. - Vec3 p0; - p0.x = position.x + (cosAngle * a.x + sinAngle * b.x) * m_viewAxisRadius * screenScale; - p0.y = position.y + (cosAngle * a.y + sinAngle * b.y) * m_viewAxisRadius * screenScale; - p0.z = position.z + (cosAngle * a.z + sinAngle * b.z) * m_viewAxisRadius * screenScale; - - const float ballRadius = 0.1f * screenScale; - dc.SetColor(Col_Magenta); - dc.DrawBall(p0, ballRadius); -} - -namespace RotationDrawHelper -{ - Axis::Axis(const ColorF& defaultColor, const ColorF& highlightColor) - { - m_colors[StateDefault] = defaultColor; - m_colors[StateHighlight] = highlightColor; - } - - void Axis::Draw(DisplayContext& dc, const Vec3& position, const Vec3& axis, float angleRadians, float angleStepRadians, float radius, bool highlighted, CBaseObject* object, float screenScale) - { - if (static_cast(dc.view)->GetType() != ET_ViewportCamera || object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - bool set = dc.SetDrawInFrontMode(true); - - // Draw the front facing arc - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, 0.f, 360.f, RAD2DEG(angleStepRadians), axis); - - dc.SetDrawInFrontMode(set); - } - else - { - // Draw the front facing arc - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, RAD2DEG(angleRadians) - 90.f, 180.f, RAD2DEG(angleStepRadians), axis); - - // Draw the back side - dc.SetColor(!highlighted ? Col_Gray : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, RAD2DEG(angleRadians) + 90.f, 180.f, RAD2DEG(angleStepRadians), axis); - } - - static bool drawAxisMidPoint = false; - if (drawAxisMidPoint) - { - const float kBallRadius = 0.085f; - Vec3 a; - Vec3 b; - GetBasisVectors(axis, a, b); - - float cosAngle = cos(angleRadians); - float sinAngle = sin(angleRadians); - - Vec3 offset; - offset.x = position.x + (cosAngle * a.x + sinAngle * b.x) * screenScale * radius; - offset.y = position.y + (cosAngle * a.y + sinAngle * b.y) * screenScale * radius; - offset.z = position.z + (cosAngle * a.z + sinAngle * b.z) * screenScale * radius; - - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawBall(offset, kBallRadius * screenScale); - } - } - - void Axis::GenerateHitTestGeometry([[maybe_unused]] HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - m_vertices.clear(); - - // The number of vertices relies on the angleStepRadians, the smaller the angle, the higher the vertex count. - int numVertices = static_cast(std::ceil(g_PI2 / angleStepRadians)); - - Vec3 a; - Vec3 b; - GetBasisVectors(axis, a, b); - - // The geometry is calculated by computing a circle aligned to the specified axis. - float angle = 0.f; - for (int i = 0; i < numVertices; ++i) - { - float cosAngle = cos(angle); - float sinAngle = sin(angle); - - Vec3 p; - p.x = position.x + (cosAngle * a.x + sinAngle * b.x) * radius * screenScale; - p.y = position.y + (cosAngle * a.y + sinAngle * b.y) * radius * screenScale; - p.z = position.z + (cosAngle * a.z + sinAngle * b.z) * radius * screenScale; - m_vertices.push_back(p); - - angle += angleStepRadians; - } - } - - bool Axis::IntersectRayWithQuad(const Ray& ray, Vec3 quad[4], Vec3& contact) - { - contact = Vec3(); - - // Tests ray vs. two quads, the front facing quad and a back facing quad. - // will return true if an intersection occurs and the world space position of the contact. - return (Intersect::Ray_Triangle(ray, quad[0], quad[1], quad[2], contact) || Intersect::Ray_Triangle(ray, quad[0], quad[2], quad[3], contact) || - Intersect::Ray_Triangle(ray, quad[0], quad[2], quad[1], contact) || Intersect::Ray_Triangle(ray, quad[0], quad[3], quad[2], contact)); - } - - bool Axis::HitTest(CBaseObject* object, HitContext& hc, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - AffineParts ap; - ap.Decompose(object->GetWorldTM()); - - Vec3 position = ap.pos; - - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - // Generate intersection testing geometry - GenerateHitTestGeometry(hc, position, radius, angleStepRadians, axis, screenScale); - - Ray ray; - ray.origin = hc.raySrc; - ray.direction = hc.rayDir; - - // Calculate the face normal with the first two vertices in the intersection geometry. - Vec3 vdir0 = (m_vertices[0] - m_vertices[1]).GetNormalized(); - Vec3 vdir1 = (m_vertices[2] - m_vertices[1]).GetNormalized(); - - Vec3 normal; - if (!hc.b2DViewport) - { - normal = hc.view->GetViewTM().GetColumn1(); - } - else - { - normal = hc.view->GetConstructionPlane()->n; - } - - float shortestDistance = std::numeric_limits::max(); - size_t numVertices = m_vertices.size(); - for (size_t i = 0; i < numVertices; ++i) - { - const Vec3& v0 = m_vertices[i]; - const Vec3& v1 = m_vertices[(i + 1) % numVertices]; - Vec3 right = (v0 - v1).Cross(normal).GetNormalized() * screenScale * m_hitTestWidth; - - // Calculates the quad vertices aligned to the face normal. - Vec3 quad[4]; - quad[0] = v0 + right; - quad[1] = v1 + right; - quad[2] = v1 - right; - quad[3] = v0 - right; - - Vec3 contact; - if (IntersectRayWithQuad(ray, quad, contact)) - { - Vec3 intersectionPoint; - if (PointToLineDistance(v0, v1, contact, intersectionPoint)) - { - // Ensure the intersection is within the quad's extents - float distanceToIntersection = intersectionPoint.GetDistance(contact); - if (distanceToIntersection < shortestDistance) - { - shortestDistance = distanceToIntersection; - } - } - } - } - - // if shortestDistance is less than the maximum possible distance, we have an intersection. - if (shortestDistance < std::numeric_limits::max() - FLT_EPSILON) - { - hc.object = object; - hc.dist = shortestDistance; - return true; - } - - return false; - } - - void Axis::DebugDrawHitTestSurface(DisplayContext& dc, HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - // Generate the geometry for rendering. - GenerateHitTestGeometry(hc, position, radius, angleStepRadians, axis, screenScale); - - // Calculate the face normal with the first two vertices in the intersection geometry. - Vec3 vdir0 = (m_vertices[0] - m_vertices[1]).GetNormalized(); - Vec3 vdir1 = (m_vertices[2] - m_vertices[1]).GetNormalized(); - - Vec3 normal; - if (!hc.b2DViewport) - { - normal = hc.view->GetViewTM().GetColumn1(); - } - else - { - normal = hc.view->GetConstructionPlane()->n; - } - - float shortestDistance = std::numeric_limits::max(); - - Ray ray; - ray.origin = hc.raySrc; - ray.direction = hc.rayDir; - - size_t numVertices = m_vertices.size(); - for (size_t i = 0; i < numVertices; ++i) - { - const Vec3& v0 = m_vertices[i]; - const Vec3& v1 = m_vertices[(i + 1) % numVertices]; - Vec3 right = (v0 - v1).Cross(normal).GetNormalized() * screenScale * m_hitTestWidth; - - // Calculates the quad vertices aligned to the face normal. - Vec3 quad[4]; - quad[0] = v0 + right; - quad[1] = v1 + right; - quad[2] = v1 - right; - quad[3] = v0 - right; - - // Draw double sided quad to ensure it is always visible regardless of camera orientation. - dc.DrawQuad(quad[0], quad[1], quad[2], quad[3]); - dc.DrawQuad(quad[3], quad[2], quad[1], quad[0]); - - Vec3 contact; - if (IntersectRayWithQuad(ray, quad, contact)) - { - Vec3 intersectionPoint; - if (PointToLineDistance(v0, v1, contact, intersectionPoint)) - { - // Ensure the intersection is within the quad's extents - float distanceToIntersection = intersectionPoint.GetDistance(contact); - if (distanceToIntersection < shortestDistance) - { - shortestDistance = distanceToIntersection; - - // Highlight the quad at which an intersection occurred. - auto c = dc.GetColor(); - dc.SetColor(Col_Red); - dc.DrawQuad(quad[0], quad[1], quad[2], quad[3]); - dc.DrawQuad(quad[3], quad[2], quad[1], quad[0]); - dc.SetColor(c); - } - } - } - } - } - - - namespace AngleDecorator - { - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axisToAlign, float startAngleRadians, float sweepAngleRadians, float stepAngleRadians, float radius, float screenScale) - { - float angle = startAngleRadians; - - if (fabs(sweepAngleRadians) < FLT_EPSILON || sweepAngleRadians < stepAngleRadians) - { - return; - } - - if (sweepAngleRadians > g_PI) - { - sweepAngleRadians = g_PI - (fabs(sweepAngleRadians - g_PI)); - stepAngleRadians = -stepAngleRadians; - } - - Vec3 a; - Vec3 b; - GetBasisVectors(axisToAlign, a, b); - - float cosAngle = cos(angle); - float sinAngle = sin(angle); - - // Pre-calculate the first vertex, this is useful for rendering the first handle ball. - Vec3 p0; - p0.x = position.x + (cosAngle * a.x + sinAngle * b.x) * radius * screenScale; - p0.y = position.y + (cosAngle * a.y + sinAngle * b.y) * radius * screenScale; - p0.z = position.z + (cosAngle * a.z + sinAngle * b.z) * radius * screenScale; - - const float ballRadius = 0.1f * screenScale; - - // TODO: colors should be configurable properties - dc.SetColor(0.f, 1.f, 0.f, 1.f); - dc.DrawBall(p0, ballRadius); - - float alpha = 0.5f; - dc.SetColor(0.8f, 0.8f, 0.8f, 0.5f); - - // Number of vertices is defined by stepAngleRadians, the smaller the step the higher vertex count. - int numVertices = static_cast(fabs(sweepAngleRadians / stepAngleRadians)); - if (numVertices >= 2) - { - Vec3 p1; - for (int i = 0; i < numVertices; ++i) - { - // We pre-calculated the first vertex, so we can advance the angle - angle += stepAngleRadians; - - const float cosAngle2 = cos(angle); - const float sinAngle2 = sin(angle); - - p1.x = position.x + (cosAngle2 * a.x + sinAngle2 * b.x) * radius * screenScale; - p1.y = position.y + (cosAngle2 * a.y + sinAngle2 * b.y) * radius * screenScale; - p1.z = position.z + (cosAngle2 * a.z + sinAngle2 * b.z) * radius * screenScale; - - // Draws a triangle from the object's position to p0 and p1. - dc.SetColor(0.8f, 0.8f, 0.8f, alpha); - dc.DrawTri(position, p0, p1); - - alpha += 0.5f * (i / numVertices); - p0 = p1; - } - - // Draw the end handle ball. - dc.SetColor(1.f, 0.f, 0.f, 1.f); - dc.DrawBall(p1, ballRadius); - } - } - } -} - -RotationControlConfiguration::RotationControlConfiguration() -{ - DefineConstIntCVar(RotationControl_DrawDecorators, 0, VF_NULL, "Toggles the display of the angular decorator."); - DefineConstIntCVar(RotationControl_DebugHitTesting, 0, VF_NULL, "Renders the hit testing geometry used for mouse input control."); - DefineConstIntCVar(RotationControl_AngleTracking, 0, VF_NULL, "Displays a sphere aligned to the mouse cursor direction for debugging."); -} - -#include diff --git a/Code/Sandbox/Editor/RotateTool.h b/Code/Sandbox/Editor/RotateTool.h deleted file mode 100644 index d24ff5ff39..0000000000 --- a/Code/Sandbox/Editor/RotateTool.h +++ /dev/null @@ -1,283 +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. -* -*/ -#ifndef CRYINCLUDE_EDITOR_ROTATETOOL_H -#define CRYINCLUDE_EDITOR_ROTATETOOL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#include "IObjectManager.h" -#include "EditMode/ObjectMode.h" -#include "Objects/BaseObject.h" // for CBaseObject::EventListener -#include "Objects/DisplayContext.h" -#include "Include/HitContext.h" -#endif - -//! Provides rendering utilities to support CRotateTool -namespace RotationDrawHelper -{ - //! Circle drawing and hit testing functionality over arbitrary axes - class Axis - { - public: - - //! \param defaultColor Color used to draw the camera aligned portion of the axis. - //! \param highlightColor Color used to draw the circle when it is in focus. - Axis(const ColorF& defaultColor = Col_White, const ColorF& highlightColor = Col_Yellow); - - //! Draws an axis aligned circle. - //! \param dc DisplayContext to use for rendering. - //! \param position World space position used as the center of the circle. - //! \param axis The axis by which to align the circle. - //! \param angleRadians The angle towards which the circle will be highlighted. - //! \param radius The radius of the circle. - //! \param highlighted If true it will draw the circle in the specified highlightColor. - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axis, float angleRadians, float angleStepRadians, float radius, bool highlighted, CBaseObject* object, float screenScale); - - //! Calculates a hit testing mesh (invisible) used for intersection testing. - //! \param object The object selected if hit testing return true. - //! \param hc The HitContext in which the hit object is set if an intersection is true. - //! \param radius The radius for the axis' circle. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis by which to align the intersection geometry. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - bool HitTest(CBaseObject* object, HitContext& hc, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - //! Draws the generated hit testing geometry, good for diagnostics and debugging. - //! \param dc DisplayContext to use for rendering. - //! \param hc The HitContext that contains the view direction raycast. - //! \param position World space position used as the center of the circle. - //! \param radius The radius for the axis' circle. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis by which to align the intersection geometry. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void DebugDrawHitTestSurface(DisplayContext& dc, HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - protected: - - enum States - { - StateDefault, - StateHighlight, - StateCount - }; - - ColorF m_colors[StateCount]; - - //! Defines the width of the generated hit testing geometry. - float m_hitTestWidth = 0.4f; - - //! Contains the vertices that make up the ring for the intersection testing geometry. - //! \remark Only contains the center positions, quads are generated by calculating the four vertices offset by m_hitTestWidth. - std::vector m_vertices; - - //! Generates the world space geometry necessary to perform hit testing. - //! \param hc The HitContext data. - //! \param position The world space position around which the geometry will be centered. - //! \param radius The radius of the ring. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis to which the geometry will be aligned to. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void GenerateHitTestGeometry(HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - //! Performs intersection testing between a ray and both sides of a quad - //! \param ray The ray to test (in world space) - //! \param quad An array of four Vec3 points in world space. - //! \param[out] contact The intersection position in world space at which the intersection occurred. - bool IntersectRayWithQuad(const Ray&ray, Vec3 quad[4], Vec3 & contact); - }; - - //! Provides the means to set and restore DisplayContext settings within a given scope. - class DisplayContextScope - { - public: - DisplayContextScope(DisplayContext& dc) - : m_dc(dc) - { - m_dc.DepthTestOff(); - m_dc.CullOff(); - } - - ~DisplayContextScope() - { - m_dc.DepthTestOn(); - m_dc.CullOn(); - } - - DisplayContext& m_dc; - }; - - //! Helper function that draws the representation of the inner angle of a rotation. - namespace AngleDecorator - { - //! \param dc - //! \param position World space position of the center of the decorator. - //! \param axisToAlign Axis to which the decorator will be aligned to. - //! \param startAngleRadians The starting angle from which the rotation will be performed. - //! \param sweepAngleRadians An angle that represents the sweep of the rotation arc. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param radius The radius of the decorator. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axisToAlign, float startAngleRadians, float sweepAngleRadians, float stepAngleRadians, float radius, float screenScale); - } -} - -//! Provides rotation manipulation controls. -class SANDBOX_API CRotateTool - : public CObjectMode - , public IObjectSelectCallback - , public CBaseObject::EventListener -{ - Q_OBJECT -public: - Q_INVOKABLE CRotateTool(CBaseObject* pObject = nullptr, QWidget* parent = nullptr); - virtual ~CRotateTool(); - - static const GUID& GetClassID(); - - // Registration function. - static void RegisterTool(CRegistrationContext& rc); - - void Display(DisplayContext& dc) override; - void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) override {} - bool HitTest(CBaseObject* pObject, HitContext& hc) override; - void DeleteThis() override; - bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point) override; - bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point) override; - bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point) override; - -protected: - - //! Utility to calculate the view distance ratio used to scale the tool. - float GetScreenScale(IDisplayViewport* view, CCamera* camera = nullptr); - - enum Axis - { - AxisNone, - AxisX, //! X axis visualization and hit testing - AxisY, //! Y axis visualization and hit testing - AxisZ, //! Z axis visualization and hit testing - AxisView, //! View direction axis, used to rotate along the vector from the camera to the object. - AxisCount - }; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - //! Axis visualization and hit testing - RotationDrawHelper::Axis m_axes[Axis::AxisCount]; - - //! We record the starting angle when we begin to drag an object - float m_initialViewAxisAngleRadians; - - //! The angle from the object's (or selection's) center to the mouse cursor. - float m_angleToCursor; - - //! Specified which axis is currently selected. - Axis m_highlightAxis; - - //! True when we are using the view direction rotation axis. - bool m_viewAxisRotation; - - //! True when the mouse has been pressed, becomes false on release. - bool m_draggingMouse; - - //! The last mouse position on screen when rotating. - QPoint m_lastPosition; - - //! Cumulative rotation angle in degrees. - Ang3 m_rotationAngles; - - //! The selected object. - CBaseObject* m_object; - - //! True if there has been a change in rotation that affects the object. - bool m_bTransformChanged; - - //! Sum of the total rotation angles. - float m_totalRotationAngle; - - //! Radius used to draw the XYZ axes - float m_basisAxisRadius; - - //! Radius used to draw the view direction axis - float m_viewAxisRadius; - - //! Rotation step controls the quality of the axes, a smaller angle represents a higher number of vertices. - float m_arcRotationStepRadians; - - //! Thickness of for the axis line rendering. - float m_lineThickness = 4.f; - - //! Draws angle decorator for the current rotation axis. - void DrawAngleDecorator(DisplayContext& dc); - - //! Useful for debugging and visualizing hit testing - void DrawHitTestGeometry(DisplayContext& dc, HitContext& hc); - - //! Diagnostic tool to examine view direction angle (follows mouse cursor) - void DrawViewDirectionAngleTracking(DisplayContext& dc, HitContext& hc); - - //! Callback registered to receive Selection callbacks to set m_object - bool OnSelectObject(CBaseObject* object) override; - - //! Callback to check that an object can be selected - bool CanSelectObject(CBaseObject* object) override; - - //! Callback installed on the object, used to determine destruction or deselection. - void OnObjectEvent(CBaseObject* object, int event) override; - - //! Handle key down events. - bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags) override; - - //! Retrieves the object's transformation according to the specified reference coordinate system. - Matrix34 GetTransform(RefCoordSys referenceCoordinateSystem, IDisplayViewport* view); - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - //! Calculate orientation of 3 points on screen, return 1.0f if clockwise, -1.0f if counter-clockwise - float CalculateOrientation(const QPoint& p1, const QPoint& p2, const QPoint& p3); - -private: - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - HitContext m_hc; //!< HACK: Cache the hitcontext given that it's values may differ depending on the viewport they are coming from. - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -//! Singleton that holds all the configuration cvars for the different features and debug options -//! used by the CRotationControl -class RotationControlConfiguration -{ -public: - - static RotationControlConfiguration& Get() - { - static RotationControlConfiguration instance; - return instance; - } - - //! If enabled it will draw the inner rotation decorator. - DeclareConstIntCVar(RotationControl_DrawDecorators, 0); - - //! If enabled the hit testing geometry is rendered. - DeclareConstIntCVar(RotationControl_DebugHitTesting, 0); - - //! If enabled a sphere will be drawn to represent the view axis angle to the mouse cursor. - DeclareConstIntCVar(RotationControl_AngleTracking, 0); - -private: - - RotationControlConfiguration(); - RotationControlConfiguration(const RotationControlConfiguration&) = delete; - RotationControlConfiguration& operator = (const RotationControlConfiguration&) = delete; - ~RotationControlConfiguration() {} -}; - -#endif // CRYINCLUDE_EDITOR_ROTATETOOL_H diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index 0f25b6ac6d..038af33129 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -653,12 +653,6 @@ void SEditorSettings::Save() SaveValue("Settings", "ForceSkyUpdate", gSettings.bForceSkyUpdate); - ////////////////////////////////////////////////////////////////////////// - // Vertex snapping settings - ////////////////////////////////////////////////////////////////////////// - SaveValue("Settings\\VertexSnapping", "VertexCubeSize", vertexSnappingSettings.vertexCubeSize); - SaveValue("Settings\\VertexSnapping", "RenderPenetratedBoundBox", vertexSnappingSettings.bRenderPenetratedBoundBox); - ////////////////////////////////////////////////////////////////////////// // Smart file open settings ////////////////////////////////////////////////////////////////////////// @@ -886,12 +880,6 @@ void SEditorSettings::Load() LoadValue("Settings", "ForceSkyUpdate", gSettings.bForceSkyUpdate); - ////////////////////////////////////////////////////////////////////////// - // Vertex snapping settings - ////////////////////////////////////////////////////////////////////////// - LoadValue("Settings\\VertexSnapping", "VertexCubeSize", vertexSnappingSettings.vertexCubeSize); - LoadValue("Settings\\VertexSnapping", "RenderPenetratedBoundBox", vertexSnappingSettings.bRenderPenetratedBoundBox); - ////////////////////////////////////////////////////////////////////////// // Smart file open settings ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Settings.h b/Code/Sandbox/Editor/Settings.h index 918647388a..512c6e3942 100644 --- a/Code/Sandbox/Editor/Settings.h +++ b/Code/Sandbox/Editor/Settings.h @@ -119,18 +119,6 @@ struct SDeepSelectionSettings bool bStickDuplicate; }; -////////////////////////////////////////////////////////////////////////// -// Settings for vertex snapping. -////////////////////////////////////////////////////////////////////////// -struct SVertexSnappingSettings -{ - SVertexSnappingSettings() - : vertexCubeSize(0.01f) - , bRenderPenetratedBoundBox(false) {} - float vertexCubeSize; - bool bRenderPenetratedBoundBox; -}; - ////////////////////////////////////////////////////////////////////////// struct SObjectColors { @@ -474,9 +462,6 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING // Object Highlight Settings SObjectColors objectColorSettings; - - // Vertex Snapping Settings - SVertexSnappingSettings vertexSnappingSettings; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING SSmartOpenDialogSettings smartOpenSettings; diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index d39dabf034..12fd9b1a03 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -625,7 +625,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const t.AddAction(ID_GOTO_SELECTED, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_OBJECTMODIFY_SETHEIGHT, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_MODIFY_ALIGNOBJTOSURF, ORIGINAL_TOOLBAR_VERSION); if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) { @@ -634,8 +633,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const t.AddAction(ID_EDIT_UNFREEZEALL, ORIGINAL_TOOLBAR_VERSION); } - t.AddAction(ID_OBJECTMODIFY_VERTEXSNAPPING, ORIGINAL_TOOLBAR_VERSION); - return t; } diff --git a/Code/Sandbox/Editor/Viewport.cpp b/Code/Sandbox/Editor/Viewport.cpp index ae2de224cb..1041a4f086 100644 --- a/Code/Sandbox/Editor/Viewport.cpp +++ b/Code/Sandbox/Editor/Viewport.cpp @@ -30,7 +30,6 @@ #include "Util/Ruler.h" #include "PluginManager.h" #include "Include/IRenderListener.h" -#include "EditTool.h" #include "GameEngine.h" #include "Settings.h" @@ -207,8 +206,6 @@ QtViewport::QtViewport(QWidget* parent) GetIEditor()->GetViewManager()->RegisterViewport(this); - m_pLocalEditTool = 0; - m_nCurViewportID = MAX_NUM_VIEWPORTS - 1; m_dropCallback = nullptr; // Leroy@Conffx @@ -232,8 +229,6 @@ QtViewport::QtViewport(QWidget* parent) ////////////////////////////////////////////////////////////////////////// QtViewport::~QtViewport() { - if (m_pLocalEditTool) - m_pLocalEditTool->deleteLater(); delete m_pVisibleObjectsCache; GetIEditor()->GetViewManager()->UnregisterViewport(this); @@ -258,42 +253,6 @@ void QtViewport::GetDimensions(int* pWidth, int* pHeight) const } } -////////////////////////////////////////////////////////////////////////// -CEditTool* QtViewport::GetEditTool() -{ - if (m_pLocalEditTool) - { - return m_pLocalEditTool; - } - return GetIEditor()->GetEditTool(); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::SetEditTool(CEditTool* pEditTool, bool bLocalToViewport /*=false */) -{ - if (m_pLocalEditTool == pEditTool) - { - return; - } - - if (m_pLocalEditTool) - { - m_pLocalEditTool->EndEditParams(); - } - m_pLocalEditTool = 0; - - if (bLocalToViewport) - { - m_pLocalEditTool = pEditTool; - m_pLocalEditTool->BeginEditParams(GetIEditor(), 0); - } - else - { - m_pLocalEditTool = 0; - GetIEditor()->SetEditTool(pEditTool); - } -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::RegisterRenderListener(IRenderListener* piListener) { @@ -466,12 +425,6 @@ void QtViewport::Update() m_bAdvancedSelectMode = false; bool bSpaceClick = false; - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - bSpaceClick = CheckVirtualKey(Qt::Key_Space); - } - else { bSpaceClick = CheckVirtualKey(Qt::Key_Space) & !CheckVirtualKey(Qt::Key_Shift) /*& !CheckVirtualKey(Qt::Key_Control)*/; } @@ -726,10 +679,6 @@ void QtViewport::OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons b ////////////////////////////////////////////////////////////////////////// void QtViewport::OnSetCursor() { - if (GetEditTool()) - { - GetEditTool()->OnSetCursor(this); - } } ////////////////////////////////////////////////////////////////////////// @@ -803,39 +752,23 @@ void QtViewport::OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& } ////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +void QtViewport::OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) { if (GetIEditor()->IsInGameMode()) { // Ignore key downs while in game. return; } - - if (GetEditTool()) - { - if (GetEditTool()->OnKeyDown(this, nChar, nRepCnt, nFlags)) - { - return; - } - } } ////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +void QtViewport::OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) { if (GetIEditor()->IsInGameMode()) { // Ignore key downs while in game. return; } - - if (GetEditTool()) - { - if (GetEditTool()->OnKeyUp(this, nChar, nRepCnt, nFlags)) - { - return; - } - } } ////////////////////////////////////////////////////////////////////////// @@ -1454,28 +1387,6 @@ bool QtViewport::MouseCallback(EMouseEvent event, const QPoint& point, Qt::Keybo } } - ////////////////////////////////////////////////////////////////////////// - // Asks current edit tool to handle mouse callback. - CEditTool* pEditTool = GetEditTool(); - if (pEditTool) - { - if (pEditTool->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - - // Ask all chain of parent tools if they are handling mouse event. - CEditTool* pParentTool = pEditTool->GetParentTool(); - while (pParentTool) - { - if (pParentTool->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - pParentTool = pParentTool->GetParentTool(); - } - } - return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Viewport.h b/Code/Sandbox/Editor/Viewport.h index acc5a3acfb..9979a3bb0a 100644 --- a/Code/Sandbox/Editor/Viewport.h +++ b/Code/Sandbox/Editor/Viewport.h @@ -45,7 +45,6 @@ struct DisplayContext; class CCryEditDoc; class CLayoutViewPane; class CViewManager; -class CEditTool; class CBaseObjectsCache; struct HitContext; struct IRenderListener; @@ -255,8 +254,6 @@ public: virtual void SetSupplementaryCursorStr(const QString& str) = 0; virtual void SetCursorString(const QString& str) = 0; - virtual CEditTool* GetEditTool() = 0; - virtual void SetFocus() = 0; virtual void Invalidate(BOOL bErase = 1) = 0; @@ -488,10 +485,6 @@ public: void ResetCursor(); void SetSupplementaryCursorStr(const QString& str); - virtual CEditTool* GetEditTool(); - // Assign an edit tool to viewport - virtual void SetEditTool(CEditTool* pEditTool, bool bLocalToViewport = false); - ////////////////////////////////////////////////////////////////////////// // Return visble objects cache. CBaseObjectsCache* GetVisibleObjectsCache() { return m_pVisibleObjectsCache; }; @@ -627,8 +620,6 @@ protected: // Same construction matrix is shared by all viewports. Matrix34 m_constructionMatrix[LAST_COORD_SYSTEM]; - QPointer m_pLocalEditTool; - std::vector m_cRenderListeners; typedef std::vector<_smart_ptr > PostRenderers; diff --git a/Code/Sandbox/Editor/VoxelAligningTool.cpp b/Code/Sandbox/Editor/VoxelAligningTool.cpp deleted file mode 100644 index 1d45dd2d3f..0000000000 --- a/Code/Sandbox/Editor/VoxelAligningTool.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "VoxelAligningTool.h" - -// Editor -#include "SurfaceInfoPicker.h" -#include "Objects/SelectionGroup.h" - -////////////////////////////////////////////////////////////////////////// -CVoxelAligningTool::CVoxelAligningTool() -{ - m_curObj = 0; - m_PreviewMode = ePM_Idle; - - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (!sel->IsEmpty()) - { - m_curObj = sel->GetObject(0); - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - m_q = m_curObj->GetRotation(); - } -} - -////////////////////////////////////////////////////////////////////////// -CVoxelAligningTool::~CVoxelAligningTool() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::Display([[maybe_unused]] DisplayContext& dc) -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CVoxelAligningTool::MouseCallback([[maybe_unused]] CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - // Get contrl key status. - bool bCtrlClick = (flags & MK_CONTROL); - bool bShiftClick = (flags & MK_SHIFT); - bool bOnlyCtrlClick = bCtrlClick && !bShiftClick; - - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (sel->IsEmpty() || m_curObj != sel->GetObject(0)) - { - GetIEditor()->SetEditTool(0); - return true; - } - - if (event == eMouseMove) - { - if (m_PreviewMode == ePM_Idle) - { - if (bOnlyCtrlClick) - { - if (m_curObj) - { - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - } - m_PreviewMode = ePM_Previewing; - GetIEditor()->BeginUndo(); - } - } - else if (!bOnlyCtrlClick) - { - if (m_curObj) - { - m_curObj->SetWorldTM(m_CurObjTMBeforePreviewMode); - //m_curObj->SetRotation(m_extraRot); - } - m_PreviewMode = ePM_Idle; - GetIEditor()->CancelUndo(); - } - - if (m_PreviewMode == ePM_Previewing && bOnlyCtrlClick) - { // Preview align to normal - ApplyPickedTM2CurObj(point); - } - } - - if (event == eMouseLDown && m_PreviewMode == ePM_Previewing) - { - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - GetIEditor()->AcceptUndo("Surface Normal Aligning"); - GetIEditor()->SetEditTool(NULL); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::ApplyPickedTM2CurObj(const QPoint& point, [[maybe_unused]] bool bPickOnlyTerrain) -{ - int nPickFlag = CSurfaceInfoPicker::ePOG_All; - SRayHitInfo hitInfo; - CSurfaceInfoPicker::CExcludedObjects excludeObjects; - if (m_curObj) - { - excludeObjects.Add(m_curObj); - } - CSurfaceInfoPicker surfacePicker; - if (surfacePicker.Pick(point, hitInfo, &excludeObjects, nPickFlag)) - { - m_curObj->SetPos(hitInfo.vHitPos, eObjectUpdateFlags_UserInput); - ApplyRotation(hitInfo.vHitNormal); - } -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::ApplyRotation(Vec3& normal) -{ - Vec3 zaxis = m_q * Vec3(0, 0, 1); - zaxis.Normalize(); - Quat nq; - nq.SetRotationV0V1(zaxis, normal); - m_curObj->SetRotation(nq * m_q, eObjectUpdateFlags_UserInput); -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::EndEditParams() -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CVoxelAligningTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->SetEditTool(0); - } - return false; -} - -#include diff --git a/Code/Sandbox/Editor/VoxelAligningTool.h b/Code/Sandbox/Editor/VoxelAligningTool.h deleted file mode 100644 index bfa0e19d9a..0000000000 --- a/Code/Sandbox/Editor/VoxelAligningTool.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of VoxelAligningTool, edit tool for cloning of objects.. - - -#ifndef CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H -#define CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H - -#pragma once - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#endif - -class CBaseObject; - -/*! - * CVoxelAligningTool, When created duplicate current selection, and manages cloned selection. - * - */ - -class CVoxelAligningTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CVoxelAligningTool(); - - ////////////////////////////////////////////////////////////////////////// - // Ovverides from CEditTool - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - - virtual void BeginEditParams(IEditor* ie, int flags); - virtual void EndEditParams(); - - virtual void Display(DisplayContext& dc); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - ////////////////////////////////////////////////////////////////////////// - -protected: - virtual ~CVoxelAligningTool(); - // Delete itself. - void DeleteThis() { delete this; }; - - void ApplyPickedTM2CurObj(const QPoint& point, bool bPickOnlyTerrain = false); - void ApplyRotation(Vec3& normal); - -private: - - CBaseObject* m_curObj; - Quat m_q; - - enum EPreviewMode - { - ePM_Idle, - ePM_Previewing, - }; - EPreviewMode m_PreviewMode; - Matrix34 m_CurObjTMBeforePreviewMode; -}; - - -#endif // CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H diff --git a/Code/Sandbox/Editor/editor_lib_files.cmake b/Code/Sandbox/Editor/editor_lib_files.cmake index 5696931f26..da32d6d062 100644 --- a/Code/Sandbox/Editor/editor_lib_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_files.cmake @@ -10,8 +10,6 @@ # set(FILES - NullEditTool.h - NullEditTool.cpp Translations/editor_en-us.ts Translations/assetbrowser_en-us.ts DPIAware.xml @@ -389,8 +387,6 @@ set(FILES Controls/NumberCtrl.h Controls/PreviewModelCtrl.cpp Controls/PreviewModelCtrl.h - Controls/QRollupCtrl.cpp - Controls/QRollupCtrl.h Controls/SplineCtrl.cpp Controls/SplineCtrl.h Controls/SplineCtrlEx.cpp @@ -401,8 +397,6 @@ set(FILES Controls/TimelineCtrl.h Controls/TimeOfDaySlider.cpp Controls/TimeOfDaySlider.h - Controls/ToolButton.cpp - Controls/ToolButton.h Controls/WndGridHelper.h Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp Controls/ReflectedPropertyControl/PropertyAnimationCtrl.h @@ -451,8 +445,6 @@ set(FILES CustomResolutionDlg.cpp CustomResolutionDlg.ui CustomResolutionDlg.h - Dialogs/ButtonsPanel.cpp - Dialogs/ButtonsPanel.h ErrorReportDialog.ui ErrorReportDialog.cpp ErrorReportDialog.h @@ -533,18 +525,8 @@ set(FILES Dialogs/PythonScriptsDialog.ui Dialogs/Generic/UserOptions.cpp Dialogs/Generic/UserOptions.h - ObjectCloneTool.cpp - ObjectCloneTool.h EditMode/SubObjectSelectionReferenceFrameCalculator.cpp EditMode/SubObjectSelectionReferenceFrameCalculator.h - EditMode/ObjectMode.cpp - EditMode/ObjectMode.h - RotateTool.cpp - RotateTool.h - EditTool.cpp - EditTool.h - VoxelAligningTool.cpp - VoxelAligningTool.h Export/ExportManager.cpp Export/ExportManager.h Export/OBJExporter.cpp @@ -575,7 +557,6 @@ set(FILES Dialogs/DuplicatedObjectsHandlerDlg.h DocMultiArchive.h EditMode/DeepSelection.h - EditMode/VertexSnappingModeTool.h FBXExporterDialog.h FileTypeUtils.h GridUtils.h @@ -639,8 +620,6 @@ set(FILES Material/MaterialLibrary.h Material/MaterialManager.cpp Material/MaterialManager.h - Material/MaterialPickTool.cpp - Material/MaterialPickTool.h MaterialSender.h MaterialSender.cpp Material/MaterialPythonFuncs.h @@ -742,7 +721,6 @@ set(FILES ErrorReportTableModel.h ErrorReportTableModel.cpp EditMode/DeepSelection.cpp - EditMode/VertexSnappingModeTool.cpp FBXExporterDialog.cpp FBXExporterDialog.ui FileTypeUtils.cpp diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h index 581c453919..12757f5b24 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h @@ -21,7 +21,6 @@ #include #include #include -#include #include ///////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index 4a03dcd7dc..a97bdbf2ab 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -320,14 +320,6 @@ void CComponentEntityObject::OnSelected() // Invoked when selected via tools application, so we notify sandbox. const bool wasSelected = IsSelected(); GetIEditor()->GetObjectManager()->SelectObject(this); - - // If we get here and we're not already selected in sandbox land it means - // the selection started in AZ land and we need to clear any edit tool - // the user may have selected from the rollup bar - if (GetIEditor()->GetEditTool() && !wasSelected) - { - GetIEditor()->SetEditTool(nullptr); - } } } diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h index 4bf55cfbe6..fa59ec8507 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h @@ -24,6 +24,8 @@ #include #include +#include + #include "../Editor/Objects/EntityObject.h" #include #include diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 9c917b25c0..89ef4ead7f 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1383,11 +1383,6 @@ void SandboxIntegrationManager::SetShowCircularDependencyError(const bool& showC } ////////////////////////////////////////////////////////////////////////// -void SandboxIntegrationManager::SetEditTool(const char* tool) -{ - GetIEditor()->SetEditTool(tool); -} - void SandboxIntegrationManager::LaunchLuaEditor(const char* files) { CCryEditApp::instance()->OpenLUAEditor(files); diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index 36767605b2..ea4d2fe32b 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -162,7 +162,6 @@ private: bool GetUndoSliceOverrideSaveValue() override; bool GetShowCircularDependencyError() override; void SetShowCircularDependencyError(const bool& showCircularDependencyError) override; - void SetEditTool(const char* tool) override; void LaunchLuaEditor(const char* files) override; bool IsLevelDocumentOpen() override; AZStd::string GetLevelName() override; diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp index 734d490c6c..a1ec03c2b1 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp index f735048ed0..fb8084cb6f 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp @@ -312,19 +312,6 @@ void OutlinerWidget::OnSelectionChanged(const QItemSelection& selected, const QI AzToolsFramework::EntityIdList newlyDeselected; ExtractEntityIdsFromSelection(deselected, newlyDeselected); - CEditTool* tool = GetIEditor()->GetEditTool(); - IClassDesc* classDescription = tool ? tool->GetClassDesc() : nullptr; - - if (classDescription && QString::compare(classDescription->ClassName(), "EditTool.Clone") == 0) - { - // if the user clicks an empty space or selects a different entity in the entity outliner, the clone operation will be accepted. - if ((newlySelected.empty() && !newlyDeselected.empty()) || !newlySelected.empty()) - { - tool->Accept(true); - GetIEditor()->GetSelection()->FinishChanges(); - } - } - AzToolsFramework::ScopedUndoBatch undo("Select Entity"); // initialize the selection command here to store the current selection before diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index b96ebae1ac..d2500dfd04 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -14,7 +14,6 @@ add_subdirectory(AssetProcessor) add_subdirectory(AWSNativeSDKInit) add_subdirectory(AzTestRunner) add_subdirectory(CryCommonTools) -add_subdirectory(CrySCompileServer) add_subdirectory(CryXML) add_subdirectory(HLSLCrossCompiler) add_subdirectory(HLSLCrossCompilerMETAL) diff --git a/Code/Tools/CrySCompileServer/CMakeLists.txt b/Code/Tools/CrySCompileServer/CMakeLists.txt deleted file mode 100644 index 84725a9d13..0000000000 --- a/Code/Tools/CrySCompileServer/CMakeLists.txt +++ /dev/null @@ -1,12 +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. -# - -add_subdirectory(CrySCompileServer) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt b/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt deleted file mode 100644 index ca22619c92..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt +++ /dev/null @@ -1,63 +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. -# - -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform) -ly_get_pal_tool_dirs(pal_tool_core_server_dirs ${CMAKE_CURRENT_LIST_DIR}/Core/Server/Platform) - -include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) - -if(NOT PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED OR NOT PAL_TRAIT_BUILD_HOST_TOOLS) - return() -endif() - -set(platform_tools_files) -foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) - string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_tool_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${enabled_platform}) - list(APPEND platform_tools_files ${pal_tool_dir}/pal_tools_${enabled_platform_lowercase}.cmake) -endforeach() - -ly_add_target( - NAME CrySCompileServer EXECUTABLE - NAMESPACE Legacy - FILES_CMAKE - cryscompileserver_files.cmake - PLATFORM_INCLUDE_FILES - Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - ${platform_tools_files} - ${common_dir}/${PAL_TRAIT_COMPILER_ID}/cryscompileserver_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake - INCLUDE_DIRECTORIES - PUBLIC - . - External - PRIVATE - ${pal_tool_dirs} - ${pal_tool_core_server_dirs} - BUILD_DEPENDENCIES - PRIVATE - 3rdParty::zlib - AZ::AzCore - AZ::AzFramework -) -ly_add_source_properties( - SOURCES - Core/Server/CrySimpleJobCompile.cpp - CrySCompileServer.cpp - PROPERTY COMPILE_DEFINITIONS - VALUES ${LY_PAL_TOOLS_DEFINES} -) -ly_add_source_properties( - SOURCES Core/Server/CrySimpleServer.cpp - PROPERTY COMPILE_DEFINITIONS - VALUES ${LY_PAL_TOOLS_DEFINES} -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h deleted file mode 100644 index d228fc1dc3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H -#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H -#pragma once - -#include -#include -#include - -#if defined(AZ_PLATFORM_WINDOWS) -# if !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0501 -# endif - -// Windows platform requires either a long or an unsigned long/uint64 for the -// Interlock instructions. -typedef long AtomicCountType; - -#else - -// Linux/Mac platforms don't support a long for the atomic types, only int32 or -// int64 (no unsigned support). -typedef int32_t AtomicCountType; - -#endif - -#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp deleted file mode 100644 index edbdcc6997..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "StdTypes.hpp" -#include "Error.hpp" -#include -#include "Server/CrySimpleErrorLog.hpp" -#include "Server/CrySimpleJob.hpp" - -#include -#include -#include - -ICryError::ICryError(EErrorType t) - : m_eType(t) - , m_numDupes(0) -{ -} - -void logmessage(const char* text, ...) -{ - va_list arg; - va_start(arg, text); - - char szBuffer[256]; - char* error = szBuffer; - int bufferlen = sizeof(szBuffer) - 1; - memset(szBuffer, 0, sizeof(szBuffer)); - - long req = CCrySimpleJob::GlobalRequestNumber(); - - int ret = azsnprintf(error, bufferlen, "%8ld | ", req); - - if (ret <= 0) - { - return; - } - error += ret; - bufferlen -= ret; - - time_t ltime; - time(<ime); - tm today; -#if defined(AZ_PLATFORM_WINDOWS) - localtime_s(&today, <ime); -#else - localtime_r(<ime, &today); -#endif - ret = (int)strftime(error, bufferlen, "%d/%m %H:%M:%S | ", &today); - - if (ret <= 0) - { - return; - } - error += ret; - bufferlen -= ret; - - vsnprintf(error, bufferlen, text, arg); - - AZ_TracePrintf(0, szBuffer); - - va_end(arg); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp deleted file mode 100644 index 8e432ce29a..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __DXPSERROR__ -#define __DXPSERROR__ - -#include -#include -#include "STLHelper.hpp" - -// printf wrapper to format things nicely -void logmessage(const char* text, ...); - -class ICryError -{ -public: - enum EErrorType - { - SIMPLE_ERROR = 0, - COMPILE_ERROR, - }; - - enum EOutputFormatType - { - OUTPUT_EMAIL = 0, - OUTPUT_TTY, - OUTPUT_HASH, - }; - - ICryError(EErrorType t); - virtual ~ICryError() {}; - - EErrorType GetType() const { return m_eType; } - - tdHash Hash() const { return CSTLHelper::Hash(GetErrorName() + GetErrorDetails(OUTPUT_HASH)); }; - - virtual bool Compare(const ICryError* err) const - { - if (GetType() != err->GetType()) - { - return GetType() < err->GetType(); - } - return Hash() < err->Hash(); - }; - virtual bool CanMerge([[maybe_unused]] const ICryError* err) const { return true; } - - virtual void AddDuplicate([[maybe_unused]] ICryError* err) { m_numDupes++; } - uint32_t NumDuplicates() const { return m_numDupes; } - - virtual void SetUniqueID([[maybe_unused]] int uniqueID) {} - - virtual bool HasFile() const { return false; }; - - virtual void AddCCs([[maybe_unused]] std::set& ccs) const {} - - virtual std::string GetErrorName() const = 0; - virtual std::string GetErrorDetails(EOutputFormatType outputType) const = 0; - virtual std::string GetFilename() const { return "NoFile"; } - virtual std::string GetFileContents() const { return ""; } -private: - EErrorType m_eType; - uint32_t m_numDupes; -}; - -class CSimpleError - : public ICryError -{ -public: - CSimpleError(const std::string& in_text) - : ICryError(SIMPLE_ERROR) - , m_text(in_text) {} - virtual ~CSimpleError() {} - - virtual std::string GetErrorName() const { return m_text; }; - virtual std::string GetErrorDetails([[maybe_unused]] EOutputFormatType outputType) const { return m_text; }; -private: - std::string m_text; -}; - - -#define CrySimple_ERROR(X) throw new CSimpleError(X) -#define CrySimple_SECURE_START try{ -#define CrySimple_SECURE_END }catch (const ICryError* err) {printf(err->GetErrorName().c_str()); delete err; } - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp deleted file mode 100644 index f79725f9af..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp +++ /dev/null @@ -1,334 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CSCMD5__ -#define __CSCMD5__ - -/* -* This code implements the MD5 message-digest algorithm. -* The algorithm is due to Ron Rivest. This code was -* written by Colin Plumb in 1993, no copyright is claimed. -* This code is in the public domain; do with it what you wish. -* -* Equivalent code is available from RSA Data Security, Inc. -* This code has been tested against that, and is equivalent, -* except that you don't need to include two pages of legalese -* with every copy. -* -* To compute the message digest of a chunk of bytes, declare an -* MD5Context structure, pass it to MD5Init, call MD5Update as -* needed on buffers full of bytes, and then call MD5Final, which -* will fill a supplied 16-byte array with the digest. -*/ - -/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to -not require an integer type which is exactly 32 bits. This work -draws on the changes for the same purpose by Tatu Ylonen - as part of SSH, but since I didn't actually use -that code, there is no copyright issue. I hereby disclaim -copyright in any changes I have made; this code remains in the -public domain. */ - -/* Note regarding cvs_* namespace: this avoids potential conflicts -with libraries such as some versions of Kerberos. No particular -need to worry about whether the system supplies an MD5 library, as -this file is only about 3k of object code. */ - - -struct cvs_MD5Context -{ - uint32_t buf[4]; - uint32_t bits[2]; - unsigned char in[64]; -}; - -void cvs_MD5Init(struct cvs_MD5Context* context); -void cvs_MD5Update(struct cvs_MD5Context* context, unsigned char const* buf, unsigned len); -void cvs_MD5Final(unsigned char digest[16], struct cvs_MD5Context* context); -void cvs_MD5Transform(uint32_t buf[4], const unsigned char in[64]); - -/* Little-endian byte-swapping routines. Note that these do not -depend on the size of datatypes such as uint32_t, nor do they require -us to detect the endianness of the machine we are running on. It -is possible they should be macros for speed, but I would be -surprised if they were a performance bottleneck for MD5. */ - -uint32_t getu32 (const unsigned char* addr) -{ - return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; -} - -void putu32(uint32_t data, unsigned char* addr) -{ - addr[0] = (unsigned char)data; - addr[1] = (unsigned char)(data >> 8); - addr[2] = (unsigned char)(data >> 16); - addr[3] = (unsigned char)(data >> 24); -} - -/* -* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious -* initialization constants. -*/ -void cvs_MD5Init(cvs_MD5Context& rCtx) -{ - rCtx.buf[0] = 0x67452301; - rCtx.buf[1] = 0xefcdab89; - rCtx.buf[2] = 0x98badcfe; - rCtx.buf[3] = 0x10325476; - rCtx.bits[0] = 0; - rCtx.bits[1] = 0; -} - -/* -* Update context to reflect the concatenation of another buffer full -* of bytes. -*/ -void cvs_MD5Update(cvs_MD5Context& rCtx, unsigned char const* buf, uint32_t len) -{ - uint32_t t; - - /* Update bitcount */ - - t = rCtx.bits[0]; - if ((rCtx.bits[0] = (t + ((uint32_t)len << 3)) & 0xffffffff) < t) - { - rCtx.bits[1]++; /* Carry from low to high */ - } - rCtx.bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) - { - unsigned char* p = rCtx.in + t; - - t = 64 - t; - if (len < t) - { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - cvs_MD5Transform (rCtx.buf, rCtx.in); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) - { - memcpy(rCtx.in, buf, 64); - cvs_MD5Transform (rCtx.buf, rCtx.in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(rCtx.in, buf, len); -} - -/* -* Final wrapup - pad to 64-byte boundary with the bit pattern -* 1 0* (64-bit count of bits processed, MSB-first) -*/ -void cvs_MD5Final(unsigned char digest[16], cvs_MD5Context& rCtx) -{ - unsigned count; - uint8_t* p; - - /* Compute number of bytes mod 64 */ - count = (rCtx.bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = rCtx.in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) - { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - cvs_MD5Transform (rCtx.buf, rCtx.in); - - /* Now fill the next block with 56 bytes */ - memset(rCtx.in, 0, 56); - } - else - { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - - /* Append length in bits and transform */ - putu32(rCtx.bits[0], rCtx.in + 56); - putu32(rCtx.bits[1], rCtx.in + 60); - - cvs_MD5Transform (rCtx.buf, rCtx.in); - putu32(rCtx.buf[0], digest); - putu32(rCtx.buf[1], digest + 4); - putu32(rCtx.buf[2], digest + 8); - putu32(rCtx.buf[3], digest + 12); - //memset(&rCtx,0,sizeof(rCtx)); // In case it's sensitive -} - - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - (w += f(x, y, z) + data, w &= 0xffffffff, w = w << s | w >> (32 - s), w += x) - -/* -* The core of the MD5 algorithm, this alters an existing MD5 hash to -* reflect the addition of 16 longwords of new data. MD5Update blocks -* the data and converts bytes into longwords for this routine. -*/ -void cvs_MD5Transform(uint32_t buf[4], const unsigned char inraw[64]) -{ - uint32_t a, b, c, d; - uint32_t in[16]; - int i; - - for (i = 0; i < 16; ++i) - { - in[i] = getu32 (inraw + 4 * i); - } - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -/* -#include - -int -main (int argc, char **argv) -{ - struct cvs_MD5Context context; - unsigned char checksum[16]; - int i; - int j; - - if (argc < 2) - { - fprintf (stderr, "usage: %s string-to-hash\n", argv[0]); - exit (1); - } - for (j = 1; j < argc; ++j) - { - printf ("MD5 (\"%s\") = ", argv[j]); - cvs_MD5Init (&context); - cvs_MD5Update (&context, argv[j], strlen (argv[j])); - cvs_MD5Final (checksum, &context); - for (i = 0; i < 16; i++) - { - printf ("%02x", (unsigned int) checksum[i]); - } - printf ("\n"); - } - return 0; -} -*/ - -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp deleted file mode 100644 index 390fc3f8c9..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "Mailer.h" -#include "WindowsAPIImplementation.h" - -#include -#include - -#if defined(AZ_PLATFORM_MAC) -#include -#include -#elif defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include -#include - -#pragma comment(lib,"ws2_32.lib") - - -namespace // helpers -{ - static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - - void Base64EncodeBlock(const unsigned char* in, unsigned char* out) - { - out[0] = cb64[in[0] >> 2]; - out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; - out[2] = cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)]; - out[3] = cb64[in[2] & 0x3f]; - } - - - void Base64EncodeBlock(const unsigned char* in, unsigned char* out, int len) - { - out[0] = cb64[in[0] >> 2]; - out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; - out[2] = (unsigned char) (len > 1 ? cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)] : '='); - out[3] = (unsigned char) (len > 2 ? cb64[in[2] & 0x3f] : '='); - } - - - void Base64Encode(const unsigned char* pSrc, const size_t srcLen, unsigned char* pDst, [[maybe_unused]] const size_t dstLen) - { - assert(dstLen >= 4 * ((srcLen + 2) / 3)); - - size_t len = srcLen; - for (; len > 2; len -= 3, pSrc += 3, pDst += 4) - { - Base64EncodeBlock(pSrc, pDst); - } - - if (len > 0) - { - unsigned char in[3]; - in[0] = pSrc[0]; - in[1] = len > 1 ? pSrc[1] : 0; - in[2] = 0; - Base64EncodeBlock(in, pDst, (int) len); - } - } - - - std::string Base64EncodeString(const std::string& in) - { - const size_t srcLen = in.size(); - const size_t dstLen = 4 * ((srcLen + 2) / 3); - std::string out(dstLen, 0); - - Base64Encode((const unsigned char*) in.c_str(), srcLen, (unsigned char*) out.c_str(), dstLen); - - return out; - } - - - const char* ExtractFileName(const char* filepath) - { - for (const char* p = filepath + strlen(filepath) - 1; p >= filepath; --p) - { - if (*p == '\\' || *p == '/') - { - return p + 1; - } - } - return filepath; - } -} - -AZStd::atomic_long CSMTPMailer::ms_OpenSockets = {0}; - -CSMTPMailer::CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port) - : m_server(server) - , m_username(username) - , m_password(password) - , m_port(port) - , m_winSockAvail(false) - , m_response() -{ -#if defined(AZ_PLATFORM_WINDOWS) - WSADATA wd; - m_winSockAvail = WSAStartup(MAKEWORD(1, 1), &wd) == 0; - if (!m_winSockAvail) - { - m_response += "Error: Unable to initialize WinSock 1.1\n"; - } -#endif -} - - -CSMTPMailer::~CSMTPMailer() -{ -#if defined(AZ_PLATFORM_WINDOWS) - if (m_winSockAvail) - { - WSACleanup(); - } -#endif -} - - -void CSMTPMailer::ReceiveLine(SOCKET connection) -{ - char buf[1025]; - int ret = recv(connection, buf, sizeof(buf) - 1, 0); - if (ret == SOCKET_ERROR) - { - ret = azsnprintf(buf, sizeof(buf), "Error: WinSock error %d during recv()\n", WSAGetLastError()); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - } - else - { - buf[ret] = 0; - } - m_response += buf; -} - - -void CSMTPMailer::SendLine(SOCKET connection, const char* format, ...) const -{ - char buf[2049]; - va_list args; - va_start(args, format); - int len = azvsnprintf(buf, sizeof(buf), format, args); - if (len == sizeof(buf) || len < 0) - { - buf[sizeof(buf) - 1] = '\0'; - len = sizeof(buf) - 1; - } - va_end(args); - send(connection, buf, len, 0); -} - - -void CSMTPMailer::SendRaw(SOCKET connection, const char* data, size_t dataLen) const -{ - send(connection, data, (int) dataLen, 0); -} - - -void CSMTPMailer::SendFile(SOCKET connection, const tattachment& filepath, const char* boundary) const -{ - AZ::IO::SystemFile inputFile; - const bool wasSuccessful = inputFile.Open(filepath.second.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - if (wasSuccessful) - { - SendLine(connection, "--%s\r\n", boundary); - SendLine(connection, "Content-Type: application/octet-stream\r\n"); - SendLine(connection, "Content-Transfer-Encoding: base64\r\n"); - SendLine(connection, "Content-Disposition: attachment; filename=\"%s\"\r\n", filepath.first.c_str()); - SendLine(connection, "\r\n"); - - AZ::IO::SystemFile::SizeType fileSize = inputFile.Length(); - while (fileSize) - { - const int DEF_BLOCK_SIZE = 128; // 72 - char in[3 * DEF_BLOCK_SIZE]; - size_t blockSize = fileSize > sizeof(in) ? sizeof(in) : fileSize; - inputFile.Read(blockSize, in); - - char out[4 * DEF_BLOCK_SIZE]; - Base64Encode((unsigned char*) in, blockSize, (unsigned char*) out, sizeof(out)); - SendRaw(connection, out, 4 * ((blockSize + 2) / 3)); - - SendLine(connection, "\r\n"); // seems to get sent faster if you split up the data lines - - fileSize -= blockSize; - } - } -} - - -SOCKET CSMTPMailer::Open(const char* host, unsigned short port, sockaddr_in& serverAddress) -{ - SOCKET connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (connection == INVALID_SOCKET) - { - m_response += "Error: Failed to create socket\n"; - return 0; - } - - struct addrinfo* addressInfo{}; - char portBuffer[16]; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - azsnprintf(portBuffer, AZStd::size(portBuffer), "%hu", port); - int addrInfoReturnCode = getaddrinfo(host, portBuffer, &hints, &addressInfo); - if(addrInfoReturnCode != 0) - { - char buf[1025]; - int ret = azsnprintf(buf, sizeof(buf), "Error: Host %s not found\n", host); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - m_response += buf; - closesocket(connection); - return 0; - } - - if (addressInfo) - { - ++ms_OpenSockets; - - serverAddress = *reinterpret_cast(addressInfo->ai_addr); - } - - return connection; -} - - -void CSMTPMailer::AddReceivers(SOCKET connection, const tstrcol& receivers) -{ - for (tstrcol::const_iterator it = receivers.begin(), itEnd = receivers.end(); it != itEnd; ++it) - { - if (!(*it).empty()) - { - SendLine(connection, "rcpt to: %s\r\n", (*it).c_str()); - ReceiveLine(connection); - } - } -} - - -void CSMTPMailer::AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers) -{ - tstrcol::const_iterator it = receivers.begin(); - tstrcol::const_iterator itEnd = receivers.end(); - - while (it != itEnd && (*it).empty()) - { - ++it; - } - - if (it != itEnd) - { - tstr out(receiverTag); - out += *it; - ++it; - for (; it != itEnd; ++it) - { - if (!(*it).empty()) - { - out += "; "; - out += *it; - } - } - out += "\r\n"; - SendLine(connection, out.c_str()); - } -} - - -void CSMTPMailer::SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary) -{ - for (tattachlist::const_iterator it = attachments.begin(), itEnd = attachments.end(); it != itEnd; ++it) - { - if (!(*it).first.empty() && !(*it).second.empty()) - { - SendFile(connection, *it, boundary); - } - } -} - - -bool CSMTPMailer::IsEmpty(const tstrcol& col) const -{ - if (!col.empty()) - { - for (tstrcol::const_iterator it = col.begin(), itEnd = col.end(); it != itEnd; ++it) - { - if (!(*it).empty()) - { - return false; - } - } - } - - return true; -} - - -bool CSMTPMailer::Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments) -{ - if (!m_winSockAvail) - { - return false; - } - - if (from.empty() || IsEmpty(to)) - { - return false; - } - - sockaddr_in serverAddress; - SOCKET connection = Open(m_server.c_str(), m_port, serverAddress); // SMTP telnet (usually port 25) - if (connection == INVALID_SOCKET) - { - return false; - } - - if (connect(connection, (sockaddr*) &serverAddress, sizeof(serverAddress)) != SOCKET_ERROR) - { - ReceiveLine(connection); - - SendLine(connection, "helo localhost\r\n"); - ReceiveLine(connection); - - if (!m_username.empty() && !m_password.empty()) - { - SendLine(connection, "auth login\r\n"); // most servers should implement this (todo: otherwise fall back to PLAIN or CRAM-MD5 (requiring EHLO)) - ReceiveLine(connection); - SendLine(connection, "%s\r\n", Base64EncodeString(m_username).c_str()); - ReceiveLine(connection); - SendLine(connection, "%s\r\n", Base64EncodeString(m_password).c_str()); - ReceiveLine(connection); - } - - SendLine(connection, "mail from: %s\r\n", from.c_str()); - ReceiveLine(connection); - - AddReceivers(connection, to); - AddReceivers(connection, cc); - AddReceivers(connection, bcc); - - SendLine(connection, "data\r\n"); - ReceiveLine(connection); - - SendLine(connection, "From: %s\r\n", from.c_str()); - AssignReceivers(connection, "To: ", to); - AssignReceivers(connection, "Cc: ", cc); - AssignReceivers(connection, "Bcc: ", bcc); - - SendLine(connection, "Subject: %s\r\n", subject.c_str()); - - static const char boundary[] = "------a95ed0b485e4a9b0fd4ff93f50ad06ca"; // beware, boundary should not clash with text content of message body! - - SendLine(connection, "MIME-Version: 1.0\r\n"); - SendLine(connection, "Content-Type: multipart/mixed; boundary=\"%s\"\r\n", boundary); - SendLine(connection, "\r\n"); - SendLine(connection, "This is a multi-part message in MIME format.\r\n"); - - SendLine(connection, "--%s\r\n", boundary); - SendLine(connection, "Content-Type: text/plain; charset=iso-8859-1; format=flowed\r\n"); // the used charset should support the commonly used special characters of western languages - SendLine(connection, "Content-Transfer-Encoding: 7bit\r\n"); - SendLine(connection, "\r\n"); - SendRaw(connection, body.c_str(), body.size()); - SendLine(connection, "\r\n"); - - SendAttachments(connection, attachments, boundary); - - SendLine(connection, "--%s--\r\n", boundary); - - SendLine(connection, "\r\n.\r\n"); - ReceiveLine(connection); - - SendLine(connection, "quit\r\n"); - ReceiveLine(connection); - } - else - { - char buf[1025]; - int ret = azsnprintf(buf, sizeof(buf), "Error: Failed to connect to %s:%d\n", m_server.c_str(), m_port); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - m_response += buf; - return false; - } - - closesocket(connection); - --ms_OpenSockets; - - return true; -} - - -const char* CSMTPMailer::GetResponse() const -{ - return m_response.c_str(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h deleted file mode 100644 index 29d8815056..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H -#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H -#pragma once - -#include "Common.h" -#include "Server/CrySimpleSock.hpp" -#include -#include -#include -#include -#include - -class CSMTPMailer -{ -public: - typedef std::string tstr; - typedef std::set tstrcol; - typedef std::pair tattachment; - typedef std::list tattachlist; - - static const int DEFAULT_PORT = 25; - static AZStd::atomic_long ms_OpenSockets; - -public: - CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port = DEFAULT_PORT); - ~CSMTPMailer(); - - bool Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments); - const char* GetResponse() const; - - static long GetOpenSockets() { return ms_OpenSockets; } - -private: - void ReceiveLine(SOCKET connection); - void SendLine(SOCKET connection, const char* format, ...) const; - void SendRaw(SOCKET connection, const char* data, size_t dataLen) const; - void SendFile(SOCKET connection, const tattachment& file, const char* boundary) const; - - SOCKET Open(const char* host, unsigned short port, sockaddr_in& serverAddress); - - void AddReceivers(SOCKET connection, const tstrcol& receivers); - void AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers); - void SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary); - - bool IsEmpty(const tstrcol& col) const; - -private: - - std::unique_ptr m_socket; - tstr m_server; - tstr m_username; - tstr m_password; - int m_port; - - bool m_winSockAvail; - tstr m_response; -}; - -#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp deleted file mode 100644 index 3f7d2390db..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "StdTypes.hpp" -#include "Error.hpp" -#include "STLHelper.hpp" - -#include -#include -#include -#include -#include - -#if defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include "MD5.hpp" -#include -#include - -#include -#include -#include -#include - -void CSTLHelper::Log(const std::string& rLog) -{ - const std::string Output = rLog + "\n"; - logmessage(Output.c_str()); -} - -void CSTLHelper::Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator) -{ - rRet.clear(); - std::string::size_type Pt; - std::string::size_type Start = 0; - std::string::size_type SSize = Separator.size(); - - while ((Pt = Tokens.find(Separator, Start)) != std::string::npos) - { - std::string SubStr = Tokens.substr(Start, Pt - Start); - rRet.push_back(SubStr); - Start = Pt + SSize; - } - - rRet.push_back(Tokens.substr(Start)); -} - - -void CSTLHelper::Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement) -{ - std::vector Out; - std::vector In(rSrc.c_str(), rSrc.c_str() + rSrc.size() + 1); - Replace(Out, In, rToReplace, rReplacement); - rRet = std::string(reinterpret_cast(&Out[0])); -} - -void CSTLHelper::Replace(std::vector& rRet, const std::vector& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement) -{ - rRet.clear(); - size_t SSize = rToReplace.size(); - for (size_t a = 0, Size = rTokenSrc.size(); a < Size; a++) - { - if (a + SSize < Size && strncmp((const char*)&rTokenSrc[a], rToReplace.c_str(), SSize) == 0) - { - for (size_t b = 0, RSize = rReplacement.size(); b < RSize; b++) - { - rRet.push_back(rReplacement.c_str()[b]); - } - a += SSize - 1; - } - else - { - rRet.push_back(rTokenSrc[a]); - } - } -} - -tdToken CSTLHelper::SplitToken(const std::string& rToken, const std::string& rSeparator) -{ -#undef min - using namespace std; - string Token; - Remove(Token, rToken, ' '); - - string::size_type Pt = Token.find(rSeparator); - return tdToken(Token.substr(0, Pt), Token.substr(std::min(Pt + 1, Token.size()))); -} - -void CSTLHelper::Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator) -{ - rTokenList.clear(); - for (size_t a = 0, Size = rFilter.size(); a < Size; a++) - { - rTokenList.push_back(SplitToken(rFilter[a], rSeparator)); - } -} - -void CSTLHelper::Trim(std::string& rStr, const std::string& charsToTrim) -{ - std::string::size_type Pt1 = rStr.find_first_not_of(charsToTrim); - if (Pt1 == std::string::npos) - { - // At this point the string could be empty or it could only contain 'charsToTrim' characters. - // In case it's the later then trim should be applied by leaving the string empty. - rStr = ""; - return; - } - - std::string::size_type Pt2 = rStr.find_last_not_of(charsToTrim) + 1; - - Pt2 = Pt2 - Pt1; - rStr = rStr.substr(Pt1, Pt2); -} - -void CSTLHelper::Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C) -{ - using namespace std; - AZ_PUSH_DISABLE_WARNING(4996, "-Wdeprecated-declarations") - remove_copy_if(rTokenSrc.begin(), rTokenSrc.end(), back_inserter(rTokenDst), [C](char token) { return token == C; }); - AZ_POP_DISABLE_WARNING -} - - -bool CSTLHelper::ToFile(const std::string& rFileName, const std::vector& rOut) -{ - if (rOut.size() == 0) - { - return false; - } - - AZ::IO::SystemFile outputFile; - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE); - - if (wasSuccessful == false) - { - AZ_Error("ShaderCompiler", wasSuccessful, "CSTLHelper::ToFile Could not create file: %s", rFileName.c_str()); - return false; - } - - outputFile.Write(&rOut[0], rOut.size()); - - return true; -} - -bool CSTLHelper::FromFile(const std::string& rFileName, std::vector& rIn) -{ - AZ::IO::SystemFile inputFile; - bool wasSuccess = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_WRITE); - if (!wasSuccess) - { - return false; - } - - AZ::IO::SystemFile::SizeType fileSize = inputFile.Length(); - if (fileSize <= 0) - { - return false; - } - - rIn.resize(fileSize); - AZ::IO::SystemFile::SizeType actualReadAmount = inputFile.Read(fileSize, &rIn[0]); - - return actualReadAmount == fileSize; -} - -bool CSTLHelper::ToFileCompressed(const std::string& rFileName, const std::vector& rOut) -{ - std::vector buf; - - unsigned long sourceLen = (unsigned long)rOut.size(); - unsigned long destLen = compressBound(sourceLen) + 16; - - buf.resize(destLen); - compress(buf.data(), &destLen, &rOut[0], sourceLen); - - if (destLen > 0) - { - AZ::IO::SystemFile outputFile; - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not create compressed file: %s", rFileName.c_str()); - - if (wasSuccessful == false) - { - return false; - } - - AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(&sourceLen, sizeof(sourceLen)); - AZ_Error("ShaderCompiler", bytesWritten == sizeof(sourceLen), "Could not save out size of compressed data to %s", rFileName.c_str()); - - if (bytesWritten != sizeof(sourceLen)) - { - return false; - } - - bytesWritten = outputFile.Write(buf.data(), destLen); - AZ_Error("ShaderCompiler", bytesWritten == destLen, "Could not save out compressed data to %s", rFileName.c_str()); - - if (bytesWritten != destLen) - { - return false; - } - - return true; - } - else - { - return false; - } -} - -bool CSTLHelper::FromFileCompressed(const std::string& rFileName, std::vector& rIn) -{ - std::vector buf; - AZ::IO::SystemFile inputFile; - const bool wasSuccessful = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not read: ", rFileName.c_str()); - - if (!wasSuccessful) - { - return false; - } - - AZ::IO::SystemFile::SizeType FileLen = inputFile.Length(); - AZ_Error("ShaderCompiler", FileLen > 0, "Error getting file-size of ", rFileName.c_str()); - - if (FileLen <= 0) - { - return false; - } - - unsigned long uncompressedLen = 0; - // Possible, expected, loss of data from u64 to u32. Zlib supports only unsigned long - unsigned long sourceLen = azlossy_caster((FileLen - 4)); - - buf.resize(sourceLen); - - AZ::IO::SystemFile::SizeType bytesReadIn = inputFile.Read(sizeof(uncompressedLen), &uncompressedLen); - AZ_Warning("ShaderCompiler", bytesReadIn == sizeof(uncompressedLen), "Expected to read in %d but read in %d from file %s", sizeof(uncompressedLen), bytesReadIn, rFileName.c_str()); - - bytesReadIn = inputFile.Read(buf.size(), buf.data()); - AZ_Warning("ShaderCompiler", bytesReadIn == buf.size(), "Expected to read in %d but read in %d from file %s", buf.size(), bytesReadIn, rFileName.c_str()); - - unsigned long nUncompressedBytes = uncompressedLen; - rIn.resize(uncompressedLen); - int nRes = uncompress(rIn.data(), &nUncompressedBytes, buf.data(), sourceLen); - - return nRes == Z_OK && nUncompressedBytes == uncompressedLen; -} - -////////////////////////////////////////////////////////////////////////// -bool CSTLHelper::AppendToFile(const std::string& rFileName, const std::vector& rOut) -{ - AZ::IO::SystemFile outputFile; - int openMode = AZ::IO::SystemFile::SF_OPEN_APPEND; - if (!AZ::IO::SystemFile::Exists(rFileName.c_str())) - { - openMode = AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; - } - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), openMode); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not open file for appending: %s", rFileName.c_str()); - if (wasSuccessful == false) - { - return false; - } - - [[maybe_unused]] AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(rOut.data(), rOut.size()); - AZ_Warning("ShaderCompiler", bytesWritten == rOut.size(), "Did not write out all the data to the file: %s", rFileName.c_str()); - return true; -} - -////////////////////////////////////////////////////////////////////////// -tdHash CSTLHelper::Hash(const uint8_t* pData, const size_t Size) -{ - tdHash CheckSum; - cvs_MD5Context MD5Context; - cvs_MD5Init(MD5Context); - cvs_MD5Update(MD5Context, pData, static_cast(Size)); - cvs_MD5Final(CheckSum.hash, MD5Context); - return CheckSum; -} - -static char C2A[17] = "0123456789ABCDEF"; - -std::string CSTLHelper::Hash2String(const tdHash& rHash) -{ - std::string Ret; - for (size_t a = 0, Size = std::min(sizeof(rHash.hash), 16u); a < Size; a++) - { - const uint8_t C1 = rHash[a] & 0xf; - const uint8_t C2 = rHash[a] >> 4; - Ret += C2A[C1]; - Ret += C2A[C2]; - } - return Ret; -} - -tdHash CSTLHelper::String2Hash(const std::string& rStr) -{ - assert(rStr.size() == 32); - tdHash Ret; - for (size_t a = 0, Size = std::min(rStr.size(), 32u); a < Size; a += 2) - { - const uint8_t C1 = rStr.c_str()[a]; - const uint8_t C2 = rStr.c_str()[a + 1]; - Ret[a >> 1] = C1 - (C1 >= '0' && C1 <= '9' ? '0' : 'A' - 10); - Ret[a >> 1] |= (C2 - (C2 >= '0' && C2 <= '9' ? '0' : 'A' - 10)) << 4; - } - return Ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CSTLHelper::Compress(const std::vector& rIn, std::vector& rOut) -{ - unsigned long destLen, sourceLen = (unsigned long)rIn.size(); - destLen = compressBound(sourceLen) + 16; - rOut.resize(destLen + 4); - compress(&rOut[4], &destLen, &rIn[0], sourceLen); - rOut.resize(destLen + 4); - *(uint32_t*)(&rOut[0]) = sourceLen; - return true; -} - -bool CSTLHelper::Uncompress(const std::vector& rIn, std::vector& rOut) -{ - unsigned long sourceLen = (unsigned long)rIn.size() - 4; - unsigned long nUncompressed = *(uint32_t*)(&rIn[0]); - unsigned long nUncompressedBytes = nUncompressed; - rOut.resize(nUncompressed); - int nRes = uncompress(&rOut[0], &nUncompressedBytes, &rIn[4], sourceLen); - return nRes == Z_OK && nUncompressed == nUncompressedBytes; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp deleted file mode 100644 index a7f4228d3c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __STLHELPER__ -#define __STLHELPER__ - -#include -#include - -typedef std::vector tdEntryVec; -typedef std::pair tdToken; -typedef std::vector tdTokenList; -typedef std::vector tdDataVector; -//typedef std::vector tdHash; - -struct tdHash -{ - uint8_t hash[16]; - - inline bool operator<(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) < 0; } - inline bool operator>(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) > 0; } - inline bool operator==(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) == 0; } - inline uint8_t& operator[](size_t nIndex) { return hash[nIndex]; } - inline const uint8_t& operator[](size_t nIndex) const { return hash[nIndex]; } -}; - -class CSTLHelper -{ - static tdHash Hash(const uint8_t* pData, const size_t Size); -public: - static void Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator); - static tdToken SplitToken(const std::string& rToken, const std::string& rSeparator); - static void Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator); - static void Trim(std::string& rStr, const std::string& charsToTrim); - static void Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C); - static void Replace(std::vector& rRet, const std::vector& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement); - static void Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement); - - - static bool ToFile(const std::string& rFileName, const std::vector& rOut); - static bool FromFile(const std::string& rFileName, std::vector& rIn); - - static bool AppendToFile(const std::string& rFileName, const std::vector& rOut); - - static bool ToFileCompressed(const std::string& rFileName, const std::vector& rOut); - static bool FromFileCompressed(const std::string& rFileName, std::vector& rIn); - - static bool Compress(const std::vector& rIn, std::vector& rOut); - static bool Uncompress(const std::vector& rIn, std::vector& rOut); - - - static void EndianSwizzleU64(uint64_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[7]; - pT[7] = T; - T = pT[1]; - pT[1] = pT[6]; - pT[6] = T; - T = pT[2]; - pT[2] = pT[5]; - pT[5] = T; - T = pT[3]; - pT[3] = pT[4]; - pT[4] = T; - } - static void EndianSwizzleU32(uint32_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[3]; - pT[3] = T; - T = pT[1]; - pT[1] = pT[2]; - pT[2] = T; - } - static void EndianSwizzleU16(uint16_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[1]; - pT[1] = T; - } - - - static void Log(const std::string& rLog); - - static tdHash Hash(const std::string& rStr) { return Hash(reinterpret_cast(rStr.c_str()), rStr.size()); } - static tdHash Hash(const std::vector& rData) { return Hash(&rData[0], rData.size()); } - static tdHash Hash(const std::vector& rData, size_t Size) { return Hash(&rData[0], Size); } - - static std::string Hash2String(const tdHash& rHash); - static tdHash String2Hash(const std::string& rStr); -}; - -#define CRYSIMPLE_LOG(X) CSTLHelper::Log(X) -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp deleted file mode 100644 index 9ceb6be6e2..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleCache.hpp" -#include "CrySimpleServer.hpp" - -#include -#include -#include - -#include -#include -#include - -enum EFileEntryHeaderFlags -{ - EFEHF_NONE = (0 << 0), - EFEHF_REFERENCE = (1 << 0), -}; - -#pragma pack(push, 1) -struct SFileEntryHeader -{ - char signature[4]; // entry signature. - uint32_t dataSize; // Size of entry data. - uint32_t flags; // Flags - uint8_t hash[16]; // Hash code for the data. -}; -#pragma pack(pop) - -static const int MAX_DATA_SIZE = 1024 * 1024; - -CCrySimpleCache& CCrySimpleCache::Instance() -{ - static CCrySimpleCache g_Cache; - return g_Cache; -} - -void CCrySimpleCache::Init() -{ - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_CachingEnabled = false; - m_Hit = 0; - m_Miss = 0; -} - -std::string CCrySimpleCache::CreateFileName(const tdHash& rHash) const -{ - AZStd::string Name; - Name = CSTLHelper::Hash2String(rHash).c_str(); - char Tmp[4] = "012"; - Tmp[0] = Name.c_str()[0]; - Tmp[1] = Name.c_str()[1]; - Tmp[2] = Name.c_str()[2]; - - AZ::IO::Path resultFileName = SEnviropment::Instance().m_CachePath / Tmp / Name; - return std::string{ resultFileName.c_str(), resultFileName.Native().size() }; -} - - -bool CCrySimpleCache::Find(const tdHash& rHash, tdDataVector& rData) -{ - if (!m_CachingEnabled) - { - return false; - } - - CCrySimpleMutexAutoLock Lock(m_Mutex); - tdEntries::iterator it = m_Entries.find(rHash); - if (it != m_Entries.end()) - { - tdData::iterator dataIt = m_Data.find(it->second); - if (dataIt == m_Data.end()) - { - m_Miss++; - return false; - } - m_Hit++; - rData = dataIt->second; - return true; - } - m_Miss++; - return false; -} - -void CCrySimpleCache::Add(const tdHash& rHash, const tdDataVector& rData) -{ - if (!m_CachingEnabled) - { - return; - } - if (rData.size() > 0) - { - SFileEntryHeader hdr; - memcpy(hdr.signature, "SHDR", 4); - hdr.dataSize = (uint32_t)rData.size(); - hdr.flags = EFEHF_NONE; - memcpy(hdr.hash, &rHash, sizeof(hdr.hash)); - const uint8_t* pData = &rData[0]; - - tdHash DataHash = CSTLHelper::Hash(rData); - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_Entries[rHash] = DataHash; - if (m_Data.find(DataHash) == m_Data.end()) - { - m_Data[DataHash] = rData; - } - else - { - hdr.flags |= EFEHF_REFERENCE; - hdr.dataSize = sizeof(tdHash); - pData = reinterpret_cast(&DataHash); - } - } - - - - tdDataVector buf; - buf.resize(sizeof(hdr) + hdr.dataSize); - memcpy(&buf[0], &hdr, sizeof(hdr)); - memcpy(&buf[sizeof(hdr)], pData, hdr.dataSize); - - tdDataVector* pPendingCacheEntry = new tdDataVector(buf); - { - CCrySimpleMutexAutoLock LockFile(m_FileMutex); - m_PendingCacheEntries.push_back(pPendingCacheEntry); - if (m_PendingCacheEntries.size() > 10000) - { - printf("Warning: Too many pending entries not saved to disk!!!"); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CCrySimpleCache::LoadCacheFile(const std::string& filename) -{ - AZ::u64 startTimeInMillis = AZStd::GetTimeUTCMilliSecond(); - - printf("Loading shader cache from %s\n", filename.c_str()); - - tdDataVector rData; - - tdHash hash; - - bool bLoadedOK = true; - - uint32_t Loaded = 0; - uint32_t num = 0; - - uint64_t nFilePos = 0; - - ////////////////////////////////////////////////////////////////////////// - AZ::IO::SystemFile cacheFile; - const bool wasSuccessful = cacheFile.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - if (!wasSuccessful) - { - return false; - } - - AZ::IO::SystemFile::SizeType fileSize = cacheFile.Length(); - - uint64_t SizeAdded = 0; - uint64_t SizeAddedCount = 0; - uint64_t SizeSaved = 0; - uint64_t SizeSavedCount = 0; - - while (nFilePos < fileSize) - { - SFileEntryHeader hdr; - AZ::IO::SystemFile::SizeType bytesReadIn = cacheFile.Read(sizeof(hdr), &hdr); - if (bytesReadIn != sizeof(hdr)) - { - break; - } - - if (memcmp(hdr.signature, "SHDR", 4) != 0) - { - // Bad Entry! - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu because signature is bad", num, nFilePos); - break; - } - - if (hdr.dataSize > MAX_DATA_SIZE || hdr.dataSize == 0) - { - // Too big entry, probably invalid. - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu because data size is too big", num, nFilePos); - break; - } - - rData.resize(hdr.dataSize); - bytesReadIn = cacheFile.Read(hdr.dataSize, rData.data()); - if (bytesReadIn != hdr.dataSize) - { - break; - } - memcpy(&hash, hdr.hash, sizeof(hdr.hash)); - - if (hdr.flags & EFEHF_REFERENCE) - { - if (hdr.dataSize != sizeof(tdHash)) - { - // Too big entry, probably invalid. - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu, was flagged as cache reference but size was %d", num, nFilePos, hdr.dataSize); - break; - } - - bool bSkip = false; - - tdHash DataHash = *reinterpret_cast(&rData[0]); - tdData::iterator it = m_Data.find(DataHash); - if (it == m_Data.end()) - { - // Too big entry, probably invalid. - bSkip = true; // don't abort reading whole file just yet - skip only this entry - printf("\nSkipping Invalid cache entry %d\n at file position: %llu, data-hash references to not existing data ", num, nFilePos); - } - - if (!bSkip) - { - m_Entries[hash] = DataHash; - SizeSaved += it->second.size(); - SizeSavedCount++; - } - } - else - { - tdHash DataHash = CSTLHelper::Hash(rData); - m_Entries[hash] = DataHash; - if (m_Data.find(DataHash) == m_Data.end()) - { - SizeAdded += rData.size(); - m_Data[DataHash] = rData; - SizeAddedCount++; - } - else - { - SizeSaved += rData.size(); - SizeSavedCount++; - } - } - - if (num % 1000 == 0) - { - AZ::u64 endTimeInMillis = AZStd::GetTimeUTCMilliSecond(); - - Loaded = static_cast(nFilePos * 100 / fileSize); - printf("\rLoad:%3u%% %6uk t=%llus Compress: (Count)%llu%% %lluk:%lluk (MB)%llu%% %lluMB:%lluMB", Loaded, num / 1000u, (endTimeInMillis - startTimeInMillis), - SizeAddedCount / AZStd::GetMax((SizeAddedCount + SizeSavedCount) / 100ull, 1ull), - SizeAddedCount / 1000, SizeSavedCount / 1000, - SizeAdded / AZStd::GetMax((SizeAdded + SizeSaved) / 100ull, 1ull), - SizeAdded / (MAX_DATA_SIZE), SizeSaved / (MAX_DATA_SIZE)); - } - - num++; - nFilePos += hdr.dataSize + sizeof(SFileEntryHeader); - } - - printf("\n%d shaders loaded from cache\n", num); - - return bLoadedOK; -} - -void CCrySimpleCache::Finalize() -{ - m_CachingEnabled = true; - printf("\n caching enabled\n"); -} - -////////////////////////////////////////////////////////////////////////// -void CCrySimpleCache::ThreadFunc_SavePendingCacheEntries() -{ - // Check pending entries and save them to disk. - bool bListEmpty = false; - do - { - tdDataVector* pPendingCacheEntry = 0; - - { - CCrySimpleMutexAutoLock LockFile(m_FileMutex); - if (!m_PendingCacheEntries.empty()) - { - pPendingCacheEntry = m_PendingCacheEntries.front(); - m_PendingCacheEntries.pop_front(); - } - //CSTLHelper::AppendToFile( SEnviropment::Instance().m_CachePath+"Cache.dat",buf ); - bListEmpty = m_PendingCacheEntries.empty(); - } - - if (pPendingCacheEntry) - { - AZ::IO::Path cacheDatPath = SEnviropment::Instance().m_CachePath / "Cache.dat"; - CSTLHelper::AppendToFile(std::string{ cacheDatPath.c_str(), cacheDatPath.Native().size() }, *pPendingCacheEntry); - delete pPendingCacheEntry; - } - } while (!bListEmpty); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp deleted file mode 100644 index 5f8feab64c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLECACHE__ -#define __CRYSIMPLECACHE__ - -#include "CrySimpleMutex.hpp" - -#include - -#include -#include -#include - -/*class CCrySimpleCacheEntry -{ - tdCache -public: -protected: -private: -};*/ - -typedef std::map tdEntries; -typedef std::map tdData; - -class CCrySimpleCache -{ - volatile bool m_CachingEnabled; - int m_Hit; - int m_Miss; - tdEntries m_Entries; - tdData m_Data; - CCrySimpleMutex m_Mutex; - CCrySimpleMutex m_FileMutex; - - std::list m_PendingCacheEntries; - std::string CreateFileName(const tdHash& rHash) const; - -public: - void Init(); - bool Find(const tdHash& rHash, tdDataVector& rData); - void Add(const tdHash& rHash, const tdDataVector& rData); - - bool LoadCacheFile(const std::string& filename); - void Finalize(); - - void ThreadFunc_SavePendingCacheEntries(); - - static CCrySimpleCache& Instance(); - - - std::list& PendingCacheEntries(){return m_PendingCacheEntries; } - int Hit() const{return m_Hit; } - int Miss() const{return m_Miss; } - int EntryCount() const{return static_cast(m_Entries.size()); } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp deleted file mode 100644 index 6fe019da53..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleErrorLog.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleJob.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#ifdef _MSC_VER -#include -#include -#endif -#ifdef UNIX -#include -#endif - -static unsigned int volatile g_bSendingMail = false; -static unsigned int volatile g_nMailNum = 0; - -CCrySimpleErrorLog& CCrySimpleErrorLog::Instance() -{ - static CCrySimpleErrorLog g_Cache; - return g_Cache; -} - -CCrySimpleErrorLog::CCrySimpleErrorLog() -{ - m_lastErrorTime = 0; -} - -void CCrySimpleErrorLog::Init() -{ -} - -bool CCrySimpleErrorLog::Add(ICryError* err) -{ - CCrySimpleMutexAutoLock Lock(m_LogMutex); - - if (m_Log.size() > 150) - { - // too many, just throw this error away - return false; // no ownership of this error - } - - m_Log.push_back(err); - - m_lastErrorTime = AZStd::GetTimeUTCMilliSecond(); - - return true; // take ownership of this error -} - -inline bool CmpError(ICryError* a, ICryError* b) -{ - return a->Compare(b); -} - -void CCrySimpleErrorLog::SendMail() -{ - CSMTPMailer::tstrcol Rcpt; - - std::string mailBody; - - tdEntryVec RcptVec; - CSTLHelper::Tokenize(RcptVec, SEnviropment::Instance().m_FailEMail, ";"); - - for (size_t i = 0; i < RcptVec.size(); i++) - { - Rcpt.insert(RcptVec[i]); - } - - tdErrorList tempLog; - { - CCrySimpleMutexAutoLock Lock(m_LogMutex); - m_Log.swap(tempLog); - } -#if defined(_MSC_VER) - { - char compName[256]; - DWORD size = ARRAYSIZE(compName); - - typedef BOOL (WINAPI * FP_GetComputerNameExA)(COMPUTER_NAME_FORMAT, LPSTR, LPDWORD); - FP_GetComputerNameExA pGetComputerNameExA = (FP_GetComputerNameExA) GetProcAddress(LoadLibrary("kernel32.dll"), "GetComputerNameExA"); - - if (pGetComputerNameExA) - { - pGetComputerNameExA(ComputerNamePhysicalDnsFullyQualified, compName, &size); - } - else - { - GetComputerName(compName, &size); - } - - mailBody += std::string("Report sent from ") + compName + "...\n\n"; - } -#endif - { - bool dedupe = SEnviropment::Instance().m_DedupeErrors; - - std::vector errors; - - if (!dedupe) - { - for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it) - { - errors.push_back(*it); - } - } - else - { - std::map uniqErrors; - for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it) - { - ICryError* err = *it; - - tdHash hash = err->Hash(); - - std::map::iterator uniq = uniqErrors.find(hash); - if (uniq != uniqErrors.end()) - { - uniq->second->AddDuplicate(err); - delete err; - } - else - { - uniqErrors[hash] = err; - } - } - - for (std::map::iterator it = uniqErrors.begin(); it != uniqErrors.end(); ++it) - { - errors.push_back(it->second); - } - } - - std::string body = mailBody; - CSMTPMailer::tstrcol cc; - CSMTPMailer::tattachlist Attachment; - - std::sort(errors.begin(), errors.end(), CmpError); - - int a = 0; - for (uint32_t i = 0; i < errors.size(); i++) - { - ICryError* err = errors[i]; - - err->SetUniqueID(a + 1); - - // doesn't have to be related to any job/error, - // we just use it to differentiate "1-IlluminationPS.txt" from "1-IlluminationPS.txt" - long req = CCrySimpleJob::GlobalRequestNumber(); - - if (err->HasFile()) - { - char Filename[1024]; - azsprintf(Filename, "%d-req%ld-%s", a + 1, req, err->GetFilename().c_str()); - - char DispFilename[1024]; - azsprintf(DispFilename, "%d-%s", a + 1, err->GetFilename().c_str()); - - std::string sErrorFile = (SEnviropment::Instance().m_ErrorPath / Filename).c_str(); - - std::vector bytes; - std::string text = err->GetFileContents(); - bytes.resize(text.size() + 1); - std::copy(text.begin(), text.end(), bytes.begin()); - while (bytes.size() && bytes[bytes.size() - 1] == 0) - { - bytes.pop_back(); - } - - CrySimple_SECURE_START - - CSTLHelper::ToFile(sErrorFile, bytes); - - Attachment.push_back(CSMTPMailer::tattachment(DispFilename, sErrorFile)); - - CrySimple_SECURE_END - } - - body += std::string("=============================================================\n"); - body += err->GetErrorDetails(ICryError::OUTPUT_EMAIL) + "\n"; - - err->AddCCs(cc); - a++; - - if (i == errors.size() - 1 || !err->CanMerge(errors[i + 1])) - { - CSMTPMailer::tstrcol bcc; - - CSMTPMailer mail("", "", SEnviropment::Instance().m_MailServer); - mail.Send(SEnviropment::Instance().m_FailEMail, Rcpt, cc, bcc, err->GetErrorName(), body, Attachment); - - a = 0; - body = mailBody; - cc.clear(); - - for (CSMTPMailer::tattachlist::iterator attach = Attachment.begin(); attach != Attachment.end(); ++attach) - { - AZ::IO::SystemFile::Delete(attach->second.c_str()); - } - - Attachment.clear(); - } - - delete err; - } - } - - g_bSendingMail = false; -} - -////////////////////////////////////////////////////////////////////////// -void CCrySimpleErrorLog::Tick() -{ - if (SEnviropment::Instance().m_MailInterval == 0) - { - return; - } - - AZ::u64 lastError = 0; - bool forceFlush = false; - - { - CCrySimpleMutexAutoLock Lock(m_LogMutex); - - if (m_Log.size() == 0) - { - return; - } - - // log has gotten pretty big, force a flush to avoid losing any errors - if (m_Log.size() > 100) - { - forceFlush = true; - } - - lastError = m_lastErrorTime; - } - - AZ::u64 t = AZStd::GetTimeUTCMilliSecond(); - if (forceFlush || t < lastError || (t - lastError) > SEnviropment::Instance().m_MailInterval * 1000) - { - if (!g_bSendingMail) - { - g_bSendingMail = true; - g_nMailNum++; - logmessage("Sending Errors Mail %d\n", g_nMailNum); - CCrySimpleErrorLog::Instance().SendMail(); - } - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp deleted file mode 100644 index 96e417f143..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEERRORLOG__ -#define __CRYSIMPLEERRORLOG__ - -#include "CrySimpleMutex.hpp" - -#include -#include - -class ICryError; -typedef std::list tdErrorList; - -class CCrySimpleErrorLog -{ - CCrySimpleMutex m_LogMutex; // protects both below variables - tdErrorList m_Log; // error log - AZ::u64 m_lastErrorTime; // last time an error came in (we mail out a little after we've stopped receiving errors) - - void Init(); - void SendMail(); - CCrySimpleErrorLog(); -public: - - bool Add(ICryError* err); - void Tick(); - - static CCrySimpleErrorLog& Instance(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp deleted file mode 100644 index 58bd88d57b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEFILEGUARD__ -#define __CRYSIMPLEFILEGUARD__ - -#include -#include - -class CCrySimpleFileGuard -{ - std::string m_FileName; -public: - CCrySimpleFileGuard(const std::string& rFileName) - : m_FileName(rFileName) - { - } - ~CCrySimpleFileGuard() - { - remove(m_FileName.c_str()); - } -}; -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp deleted file mode 100644 index 624bfd5b80..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleHTTP.hpp" -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleCache.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -////////////////////////////////////////////////////////////////////////// -class CHTTPRequest -{ - CCrySimpleSock* m_pSock; -public: - CHTTPRequest(CCrySimpleSock* pSock) - : m_pSock(pSock){} - - ~CHTTPRequest(){delete m_pSock; } - - CCrySimpleSock* Socket(){return m_pSock; } -}; - -#define HTML_HEADER "HTTP/1.1 200 OK\n\ -Server: Shader compile server %s\n\ -Content-Length: %zu\n\ -Content-Language: de (nach RFC 3282 sowie RFC 1766)\n\ -Content-Type: text/html\n\ -Connection: close\n\ -\n\ -shader compile server %s" - -#define TABLE_START "\n\ -\n\ -\n" -#define TABLE_INFO "\n\ -\n" -#define TABLE_BAR "\n\ -\n" -#define TABLE_END "
DescriptionValueMax %
%s %s \n\ -
%s %d%d \n\ -\n\ -\n\ -
%d%%
" - -std::string CreateBar(const std::string& rName, int Value, int Max, int Percentage) -{ - AZStd::string formattedString = AZStd::string::format(TABLE_BAR, rName.c_str(), Value, Max, Percentage, Percentage); - return formattedString.c_str(); -} - -std::string CreateInfoText(const std::string& rName, const std::string& rValue) -{ - AZStd::string formattedString = AZStd::string::format(TABLE_INFO, rName.c_str(), rValue.c_str()); - return formattedString.c_str(); -} - -std::string CreateInfoText(const std::string& rName, int Value) -{ - char Text[64]; - azsprintf(Text, "%d", Value); - return CreateInfoText(rName, Text); -} - -class HttpProcessRequestJob - : public AZ::Job -{ -public: - HttpProcessRequestJob(CHTTPRequest* request) - : AZ::Job(true, nullptr) - , m_request(request) { } - -protected: - void Process() override - { -#if defined(AZ_PLATFORM_WINDOWS) - FILETIME IdleTime0, IdleTime1; - FILETIME KernelTime0, KernelTime1; - FILETIME UserTime0, UserTime1; - - int Ret0 = GetSystemTimes(&IdleTime0, &KernelTime0, &UserTime0); - Sleep(100); - int Ret1 = GetSystemTimes(&IdleTime1, &KernelTime1, &UserTime1); - const int Idle = IdleTime1.dwLowDateTime - IdleTime0.dwLowDateTime; - const int Kernel = KernelTime1.dwLowDateTime - KernelTime0.dwLowDateTime; - const int User = UserTime1.dwLowDateTime - UserTime0.dwLowDateTime; - //const int Idle = IdleTime1.dwHighDateTime-IdleTime0.dwHighDateTime; - //const int Kernel = KernelTime1.dwHighDateTime-KernelTime0.dwHighDateTime; - //const int User = UserTime1.dwHighDateTime-UserTime0.dwHighDateTime; - const int Total = Kernel + User; -#else - int Ret0 = 0; - int Ret1 = 0; - int Total = 0; - int Idle = 0; -#endif - - std::string Ret = TABLE_START; - - Ret += CreateInfoText("Load:", ""); - if (Ret0 && Ret1 && Total) - { - Ret += CreateBar("CPU-Usage", Total - Idle, Total, 100 - Idle * 100 / Total); - } - - Ret += CreateBar("CompileTasks", CCrySimpleJobCompile::GlobalCompileTasks(), - CCrySimpleJobCompile::GlobalCompileTasksMax(), - CCrySimpleJobCompile::GlobalCompileTasksMax() ? - CCrySimpleJobCompile::GlobalCompileTasks() * 100 / - CCrySimpleJobCompile::GlobalCompileTasksMax() : 0); - - - Ret += CreateInfoText("Setup:", ""); - Ret += CreateInfoText("Root", SEnviropment::Instance().m_Root.c_str()); - Ret += CreateInfoText("CompilerPath", SEnviropment::Instance().m_CompilerPath.c_str()); - Ret += CreateInfoText("CachePath", SEnviropment::Instance().m_CachePath.c_str()); - Ret += CreateInfoText("TempPath", SEnviropment::Instance().m_TempPath.c_str()); - Ret += CreateInfoText("ErrorPath", SEnviropment::Instance().m_ErrorPath.c_str()); - Ret += CreateInfoText("ShaderPath", SEnviropment::Instance().m_ShaderPath.c_str()); - Ret += CreateInfoText("FailEMail", SEnviropment::Instance().m_FailEMail); - Ret += CreateInfoText("MailServer", SEnviropment::Instance().m_MailServer); - Ret += CreateInfoText("port", SEnviropment::Instance().m_port); - Ret += CreateInfoText("MailInterval", SEnviropment::Instance().m_MailInterval); - Ret += CreateInfoText("Caching", SEnviropment::Instance().m_Caching ? "Enabled" : "Disabled"); - Ret += CreateInfoText("FallbackServer", SEnviropment::Instance().m_FallbackServer == "" ? "None" : SEnviropment::Instance().m_FallbackServer); - Ret += CreateInfoText("FallbackTreshold", static_cast(SEnviropment::Instance().m_FallbackTreshold)); - Ret += CreateInfoText("DumpShaders", static_cast(SEnviropment::Instance().m_DumpShaders)); - - Ret += CreateInfoText("Cache:", ""); - Ret += CreateInfoText("Entries", CCrySimpleCache::Instance().EntryCount()); - Ret += CreateBar("Hits", CCrySimpleCache::Instance().Hit(), - CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss(), - CCrySimpleCache::Instance().Hit() * 100 / AZStd::GetMax(1, (CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss()))); - Ret += CreateInfoText("Pending Entries", static_cast(CCrySimpleCache::Instance().PendingCacheEntries().size())); - - - - Ret += TABLE_END; - - Ret += ""; - char Text[sizeof(HTML_HEADER) + 1024]; - azsprintf(Text, HTML_HEADER, __DATE__, Ret.size(), __DATE__); - Ret = std::string(Text) + Ret; - m_request->Socket()->Send(Ret); - } - -private: - std::unique_ptr m_request; -}; - -class HttpServerJob - : public AZ::Job -{ -public: - HttpServerJob(CCrySimpleHTTP* simpleHttp) - : AZ::Job(true, nullptr) - , m_simpleHttp(simpleHttp) { } - -protected: - void Process() - { - m_simpleHttp->Run(); - } -private: - CCrySimpleHTTP* m_simpleHttp; -}; - -////////////////////////////////////////////////////////////////////////// -CCrySimpleHTTP::CCrySimpleHTTP() - : m_pServerSocket(0) -{ - CrySimple_SECURE_START - - Init(); - - CrySimple_SECURE_END -} - -void CCrySimpleHTTP::Init() -{ - m_pServerSocket = new CCrySimpleSock(61480, SEnviropment::Instance().m_WhitelistAddresses); //http - m_pServerSocket->Listen(); - HttpServerJob* serverJob = new HttpServerJob(this); - serverJob->Start(); -} - -void CCrySimpleHTTP::Run() -{ - while (1) - { - // New client message, receive new client socket connection. - CCrySimpleSock* newClientSocket = m_pServerSocket->Accept(); - if(!newClientSocket) - { - continue; - } - - // HTTP Request Data for new job - CHTTPRequest* pData = new CHTTPRequest(newClientSocket); - - HttpProcessRequestJob* requestJob = new HttpProcessRequestJob(pData); - requestJob->Start(); - } -} - - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp deleted file mode 100644 index e78d6ef41d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CrySimpleHTTP__ -#define __CrySimpleHTTP__ - -#include -#include -#include - -extern bool g_Success; - -class CCrySimpleSock; - -class CCrySimpleHTTP -{ - static AZStd::atomic_long ms_ExceptionCount; - CCrySimpleSock* m_pServerSocket; - void Init(); -public: - CCrySimpleHTTP(); - - void Run(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp deleted file mode 100644 index 1e7423dc69..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJob.hpp" -#include "CrySimpleFileGuard.hpp" -#include "CrySimpleServer.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -AZStd::atomic_long CCrySimpleJob::m_GlobalRequestNumber = {0}; - -CCrySimpleJob::CCrySimpleJob(uint32_t requestIP) - : m_State(ECSJS_NONE) - , m_RequestIP(requestIP) -{ - ++m_GlobalRequestNumber; -} - -CCrySimpleJob::~CCrySimpleJob() -{ -} - - -bool CCrySimpleJob::ExecuteCommand(const std::string& rCmd, std::string& outError) -{ - const bool showStdOuput = false; // For Debug: Set to true if you want the compiler's standard ouput printed out as well. - const bool showStdErrorOuput = SEnviropment::Instance().m_PrintWarnings; - -#ifdef _MSC_VER - bool Ret = false; - DWORD ExitCode = 0; - - STARTUPINFO StartupInfo; - PROCESS_INFORMATION ProcessInfo; - memset(&StartupInfo, 0, sizeof(StartupInfo)); - memset(&ProcessInfo, 0, sizeof(ProcessInfo)); - StartupInfo.cb = sizeof(StartupInfo); - - - std::string Path = ""; - std::string::size_type Pt = rCmd.find_first_of(' '); - if (Pt != std::string::npos) - { - std::string First = std::string(rCmd.c_str(), Pt); - std::string::size_type Pt2 = First.find_last_of('/'); - if (Pt2 != std::string::npos) - { - Path = std::string(First.c_str(), Pt2); - } - else - { - Pt = std::string::npos; - } - } - - HANDLE hReadErr, hWriteErr; - - { - CreatePipe(&hReadErr, &hWriteErr, NULL, 0); - SetHandleInformation(hWriteErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - - StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - StartupInfo.hStdOutput = (showStdOuput) ? GetStdHandle(STD_OUTPUT_HANDLE) : NULL; - StartupInfo.hStdError = hWriteErr; - StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - - BOOL processCreated = CreateProcess(NULL, (char*)rCmd.c_str(), 0, 0, TRUE, CREATE_DEFAULT_ERROR_MODE, 0, Pt != std::string::npos ? Path.c_str() : 0, &StartupInfo, &ProcessInfo) != false; - - if (!processCreated) - { - outError = "Couldn't create process - missing compiler for cmd?: '" + rCmd + "'"; - } - else - { - std::string error; - - DWORD waitResult = 0; - HANDLE waitHandles[] = { ProcessInfo.hProcess, hReadErr }; - while (true) - { - //waitResult = WaitForMultipleObjects(sizeof(waitHandles) / sizeof(waitHandles[0]), waitHandles, FALSE, 1000 ); - waitResult = WaitForSingleObject(ProcessInfo.hProcess, 1000); - if (waitResult == WAIT_FAILED) - { - break; - } - - DWORD bytesRead, bytesAvailable; - while (PeekNamedPipe(hReadErr, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable) - { - char buff[4096]; - ReadFile(hReadErr, buff, sizeof(buff) - 1, &bytesRead, 0); - buff[bytesRead] = '\0'; - error += buff; - } - CSTLHelper::Trim(error," \t\r\n"); - - //if (waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT) - //break; - - if (waitResult == WAIT_OBJECT_0) - { - break; - } - } - - //if (waitResult != WAIT_TIMEOUT) - { - GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode); - if (ExitCode) - { - Ret = false; - outError = error; - } - else - { - if (showStdErrorOuput && !error.empty()) - { - AZ_Printf(0, "\n%s\n", error.c_str()); - } - Ret = true; - } - } - /* - else - { - Ret = false; - outError = std::string("Timed out executing compiler: ") + rCmd; - TerminateProcess(ProcessInfo.hProcess, 1); - } - */ - - CloseHandle(ProcessInfo.hProcess); - CloseHandle(ProcessInfo.hThread); - } - - CloseHandle(hReadErr); - if (hWriteErr) - { - CloseHandle(hWriteErr); - } - } - - return Ret; -#endif - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - std::thread::id threadId = std::this_thread::get_id(); - std::stringstream threadIdStream; - threadIdStream << threadId; - - // Multiple threads could execute a command, therefore the temporary file has to be unique per thread. - AZ::IO::Path errorTempFilePath = SEnviropment::Instance().m_TempPath / AZStd::string::format("stderr_%s.log", threadIdStream.str().c_str()); - std::string stdErrorTempFilename{ errorTempFilePath.c_str(), errorTempFilePath.Native().size() }; - - CCrySimpleFileGuard FGTmpOutput(stdErrorTempFilename); // Delete file at the end of this function - - std::string systemCmd = rCmd; - if(!showStdOuput) - { - // Standard output redirected to null to disable it - systemCmd += " > /dev/null"; - } - // Standard error ouput redirected to the temporary file - systemCmd += " 2> \"" + stdErrorTempFilename + "\""; - - int ret = system(systemCmd.c_str()); - - // Obtain standard error output - std::ifstream fileStream(stdErrorTempFilename.c_str()); - std::stringstream stdErrorStream; - stdErrorStream << fileStream.rdbuf(); - std::string stdErrorString = stdErrorStream.str(); - CSTLHelper::Trim(stdErrorString," \t\r\n"); - - if (ret != 0) - { - outError = stdErrorString; - return false; - } - else - { - if (showStdErrorOuput && !stdErrorString.empty()) - { - AZ_Printf(0, "\n%s\n", stdErrorString.c_str()); - } - return true; - } -#endif -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp deleted file mode 100644 index 839fdb1543..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOB__ -#define __CRYSIMPLEJOB__ - -#include -#include -#include -#include -#include - -class TiXmlElement; - -enum ECrySimpleJobState -{ - ECSJS_NONE, - ECSJS_DONE = 1, //this is checked on client side, don't change! - ECSJS_JOBNOTFOUND, - ECSJS_CACHEHIT, - ECSJS_ERROR, - ECSJS_ERROR_COMPILE = 5, //this is checked on client side, don't change! - ECSJS_ERROR_COMPRESS, - ECSJS_ERROR_FILEIO, - ECSJS_ERROR_INVALID_PROFILE, - ECSJS_ERROR_INVALID_PROJECT, - ECSJS_ERROR_INVALID_PLATFORM, - ECSJS_ERROR_INVALID_PROGRAM, - ECSJS_ERROR_INVALID_ENTRY, - ECSJS_ERROR_INVALID_COMPILEFLAGS, - ECSJS_ERROR_INVALID_COMPILER, - ECSJS_ERROR_INVALID_LANGUAGE, - ECSJS_ERROR_INVALID_SHADERREQUESTLINE, - ECSJS_ERROR_INVALID_SHADERLIST, -}; - -class CCrySimpleJob -{ - ECrySimpleJobState m_State; - uint32_t m_RequestIP; - static AZStd::atomic_long m_GlobalRequestNumber; - - -protected: - virtual bool ExecuteCommand(const std::string& rCmd, std::string& outError); -public: - CCrySimpleJob(uint32_t requestIP); - virtual ~CCrySimpleJob(); - - virtual bool Execute(const TiXmlElement* pElement) = 0; - - void State(ECrySimpleJobState S) - { - if (m_State < ECSJS_ERROR || S >= ECSJS_ERROR) - { - m_State = S; - } - } - ECrySimpleJobState State() const { return m_State; } - const uint32_t& RequestIP() const { return m_RequestIP; } - static long GlobalRequestNumber() { return m_GlobalRequestNumber; } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp deleted file mode 100644 index dd2bac8db2..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJobCache.hpp" -#include "CrySimpleCache.hpp" - -#include -#include -#include -#include -#include - -CCrySimpleJobCache::CCrySimpleJobCache(uint32_t requestIP) - : CCrySimpleJob(requestIP) -{ -} - -void CCrySimpleJobCache::CheckHashID(std::vector& rVec, size_t Size) -{ - m_HashID = CSTLHelper::Hash(rVec, Size); - if (CCrySimpleCache::Instance().Find(m_HashID, rVec)) - { - State(ECSJS_CACHEHIT); - logmessage("\r"); // Just update cache hit number - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp deleted file mode 100644 index 834a3c687a..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCACHE__ -#define __CRYSIMPLEJOBCACHE__ - -#include "CrySimpleJob.hpp" -#include - -class CCrySimpleJobCache - : public CCrySimpleJob -{ - tdHash m_HashID; - -protected: - - void CheckHashID(std::vector& rVec, size_t Size); - -public: - CCrySimpleJobCache(uint32_t requestIP); - - tdHash HashID() const{return m_HashID; } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp deleted file mode 100644 index 5acc0bc2c8..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - - -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile.hpp" -#include "CrySimpleFileGuard.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleCache.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#undef AZ_RESTRICTED_SECTION -#define CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 1 -#endif - -#define MAX_COMPILER_WAIT_TIME (60 * 1000) - -AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasks = {0}; -AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasksMax = {0}; -volatile int32_t CCrySimpleJobCompile::m_RemoteServerID = 0; -volatile int64_t CCrySimpleJobCompile::m_GlobalCompileTime = 0; - -struct STimer -{ - int64_t m_freq; - STimer() - { - QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq); - } - int64_t GetTime() const - { - int64_t t; - QueryPerformanceCounter((LARGE_INTEGER*)&t); - return t; - } - - double TimeToSeconds(int64_t t) - { - return ((double)t) / m_freq; - } -}; - - -STimer g_Timer; - -// This function validates executables up to version 21 -// because it's received within the compilation flags. -bool ValidateExecutableStringLegacy(const AZStd::string& executableString) -{ - AZStd::string::size_type endOfCommand = executableString.find(" "); - - // Game always sends some type of options after the command. If we don't - // have a space then that implies that there are no options. Reject the - // command as someone being malicious - if (endOfCommand == AZStd::string::npos) - { - return false; - } - - AZStd::string commandString = executableString.substr(0, endOfCommand); - - // The game never sends a parent directory in the compiler flags so lets - // reject any commands that have .. in it - if (commandString.find("..") != AZStd::string::npos) - { - return false; - } - - // Though the code later down would fail gracefully reject any absolute paths here - if (commandString.find("\\\\") != AZStd::string::npos || - commandString.find(":") != AZStd::string::npos) - { - return false; - } - - // Only allow a subset of executables to be accepted... - if (commandString.find("fxc.exe") == AZStd::string::npos && - commandString.find("FXC.exe") == AZStd::string::npos && - commandString.find("HLSLcc.exe") == AZStd::string::npos && - commandString.find("HLSLcc_dedicated.exe") == AZStd::string::npos && - commandString.find("DXProvoShaderCompiler.exe") == AZStd::string::npos && - commandString.find("dxcGL") == AZStd::string::npos && - commandString.find("dxcMetal") == AZStd::string::npos) - { - return false; - } - - return true; -} - -CCrySimpleJobCompile::CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector* pRVec) - : CCrySimpleJobCache(requestIP) - , m_Version(Version) - , m_pRVec(pRVec) -{ - ++m_GlobalCompileTasks; - if (m_GlobalCompileTasksMax < m_GlobalCompileTasks) - { - //Need this cast as the copy assignment operator is implicitly deleted - m_GlobalCompileTasksMax = static_cast(m_GlobalCompileTasks); - } -} - -CCrySimpleJobCompile::~CCrySimpleJobCompile() -{ - --m_GlobalCompileTasks; -} - -bool CCrySimpleJobCompile::Execute(const TiXmlElement* pElement) -{ - std::vector& rVec = *m_pRVec; - - size_t Size = SizeOf(rVec); - - CheckHashID(rVec, Size); - - if (State() == ECSJS_CACHEHIT) - { - State(ECSJS_DONE); - return true; - } - - if (!SEnviropment::Instance().m_FallbackServer.empty() && m_GlobalCompileTasks > SEnviropment::Instance().m_FallbackTreshold) - { - tdEntryVec ServerVec; - CSTLHelper::Tokenize(ServerVec, SEnviropment::Instance().m_FallbackServer, ";"); - uint32_t Idx = m_RemoteServerID++; - uint32_t Count = (uint32_t)ServerVec.size(); - std::string Server = ServerVec[Idx % Count]; - printf(" Remote Compile on %s ...\n", Server.c_str()); - CCrySimpleSock Sock(Server, SEnviropment::Instance().m_port); - if (Sock.Valid()) - { - Sock.Forward(rVec); - std::vector Tmp; - if (Sock.Backward(Tmp)) - { - rVec = Tmp; - if (Tmp.size() <= 4 || (m_Version == EPV_V002 && Tmp[4] != ECSJS_DONE)) - { - State(ECSJS_ERROR_COMPILE); - CrySimple_ERROR("failed to compile request"); - return false; - } - State(ECSJS_DONE); - //printf("done\n"); - } - else - { - printf("failed, fallback to local\n"); - } - } - else - { - printf("failed, fallback to local\n"); - } - } - if (State() == ECSJS_NONE) - { - if (!Compile(pElement, rVec) || rVec.size() == 0) - { - State(ECSJS_ERROR_COMPILE); - CrySimple_ERROR("failed to compile request"); - return false; - } - - tdDataVector rDataRaw; - rDataRaw.swap(rVec); - if (!CSTLHelper::Compress(rDataRaw, rVec)) - { - State(ECSJS_ERROR_COMPRESS); - CrySimple_ERROR("failed to compress request"); - return false; - } - State(ECSJS_DONE); - } - - // Cache compiled data - const char* pCaching = pElement->Attribute("Caching"); - if (State() != ECSJS_ERROR && (!pCaching || std::string(pCaching) == "1")) - { - CCrySimpleCache::Instance().Add(HashID(), rVec); - } - - return true; -} - -bool CCrySimpleJobCompile::Compile(const TiXmlElement* pElement, std::vector& rVec) -{ - AZStd::string platform; - AZStd::string compiler; - AZStd::string language; - AZStd::string shaderPath; - - if (m_Version >= EPV_V0023) - { - // NOTE: These attributes were alredy validated. - platform = pElement->Attribute("Platform"); - compiler = pElement->Attribute("Compiler"); - language = pElement->Attribute("Language"); - - shaderPath = AZStd::string::format("%s%s-%s-%s/", SEnviropment::Instance().m_ShaderPath.c_str(), platform.c_str(), compiler.c_str(), language.c_str()); - } - else - { - // In previous versions Platform attribute is the language - platform = "N/A"; - language = pElement->Attribute("Platform"); - - // Map shader language to shader compiler key - const AZStd::unordered_map languageToCompilerMap - { - { - "GL4", SEnviropment::m_GLSL_HLSLcc - },{ - "GLES3_0", SEnviropment::m_GLSL_HLSLcc - },{ - "GLES3_1", SEnviropment::m_GLSL_HLSLcc - },{ - "DX11", SEnviropment::m_D3D11_FXC - },{ - "METAL", SEnviropment::m_METAL_HLSLcc - },{ - "ORBIS", SEnviropment::m_Orbis_DXC - },{ - "JASPER", SEnviropment::m_Jasper_FXC - } - }; - - auto foundShaderLanguage = languageToCompilerMap.find(language); - if (foundShaderLanguage == languageToCompilerMap.end()) - { - State(ECSJS_ERROR_INVALID_LANGUAGE); - CrySimple_ERROR("Trying to compile with invalid shader language"); - return false; - } - - if (m_Version < EPV_V0022) - { - compiler = "N/A"; // Compiler exe will be specified inside 'compile flags', this variable won't be used - } - else - { - compiler = foundShaderLanguage->second; - - if (!SEnviropment::Instance().IsShaderCompilerValid(compiler)) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("Trying to compile with invalid shader compiler"); - return false; - } - } - - shaderPath = AZStd::string::format("%s%s/", SEnviropment::Instance().m_ShaderPath.c_str(), language.c_str()); - } - - shaderPath = AZ::IO::PathView(shaderPath).LexicallyNormal().Native(); - if (!IsPathValid(shaderPath)) - { - State(ECSJS_ERROR); - CrySimple_ERROR("Shaders output path is invalid"); - return false; - } - - // Create shaders directory - AZ::IO::SystemFile::CreateDir( shaderPath.c_str() ); - - const char* pProfile = pElement->Attribute("Profile"); - const char* pProgram = pElement->Attribute("Program"); - const char* pEntry = pElement->Attribute("Entry"); - const char* pCompileFlags = pElement->Attribute("CompileFlags"); - const char* pShaderRequestLine = pElement->Attribute("ShaderRequest"); - - if (!pProfile) - { - State(ECSJS_ERROR_INVALID_PROFILE); - CrySimple_ERROR("failed to extract Profile of the request"); - return false; - } - if (!pProgram) - { - State(ECSJS_ERROR_INVALID_PROGRAM); - CrySimple_ERROR("failed to extract Program of the request"); - return false; - } - if (!pEntry) - { - State(ECSJS_ERROR_INVALID_ENTRY); - CrySimple_ERROR("failed to extract Entry of the request"); - return false; - } - if (!pShaderRequestLine) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("failed to extract ShaderRequest of the request"); - return false; - } - if (!pCompileFlags) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("failed to extract CompileFlags of the request"); - return false; - } - - // Validate that the shader request line has a set of open/close parens as - // the code below this expects at least the open paren to be in the string. - // Without the open paren the code below will crash the compiler - std::string strippedShaderRequestLine(pShaderRequestLine); - const size_t locationOfOpenParen = strippedShaderRequestLine.find("("); - const size_t locationOfCloseParen = strippedShaderRequestLine.find(")"); - if (locationOfOpenParen == std::string::npos || - locationOfCloseParen == std::string::npos || locationOfCloseParen < locationOfOpenParen) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("invalid ShaderRequest attribute"); - return false; - } - - static AZStd::atomic_long nTmpCounter = { 0 }; - ++nTmpCounter; - - const auto tmpIndex = AZStd::string::format("%ld", static_cast(nTmpCounter)); - const AZ::IO::Path TmpIn = SEnviropment::Instance().m_TempPath / (tmpIndex + ".In"); - const AZ::IO::Path TmpOut = SEnviropment::Instance().m_TempPath / (tmpIndex + ".Out"); - CCrySimpleFileGuard FGTmpIn(TmpIn.c_str()); - CCrySimpleFileGuard FGTmpOut(TmpOut.c_str()); - CSTLHelper::ToFile(TmpIn.c_str(), std::vector(pProgram, &pProgram[strlen(pProgram)])); - - AZ::IO::Path compilerPath = SEnviropment::Instance().m_CompilerPath; - AZStd::string command; - if (m_Version >= EPV_V0022) - { - AZStd::string compilerExecutable; - bool validCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(compiler, compilerExecutable); - if (!validCompiler) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("Trying to compile with unknown compiler"); - return false; - } - - AZStd::string commandStringToFormat = (compilerPath / compilerExecutable).Native(); - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - // Surrounding compiler path+executable with quotes to support spaces in the path. - // NOTE: Executable has a space at the end on purpose, inserting quote before. - commandStringToFormat.insert(0, "\""); - commandStringToFormat.insert(commandStringToFormat.length()-1, "\""); -#endif - - commandStringToFormat.append(pCompileFlags); - - if (strstr(pCompileFlags, "-fxc") != nullptr) - { - AZStd::string fxcCompilerExecutable; - bool validFXCCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(SEnviropment::m_D3D11_FXC, fxcCompilerExecutable); - if (!validFXCCompiler) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("FXC compiler executable cannot be found"); - return false; - } - - AZ::IO::Path fxcLocation = compilerPath / fxcCompilerExecutable; - - // Handle an extra string parameter to specify the base directory where the fxc compiler is located - command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), fxcLocation.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - else - { - command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - } - else - { - if (!ValidateExecutableStringLegacy(pCompileFlags)) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("CompileFlags failed validation"); - return false; - } - - if (strstr(pCompileFlags, "-fxc=\"%s") != nullptr) - { - // Check that the string after the %s is a valid shader compiler - // executable - AZStd::string tempString(pCompileFlags); - const AZStd::string::size_type fxcOffset = tempString.find("%s") + 2; - const AZStd::string::size_type endOfFxcString = tempString.find(" ", fxcOffset); - tempString = tempString.substr(fxcOffset, endOfFxcString); - if (!ValidateExecutableStringLegacy(tempString)) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("CompileFlags failed validation"); - return false; - } - - // Handle an extra string parameter to specify the base directory where the fxc compiler is located - command = AZStd::move(AZStd::string::format(pCompileFlags, compilerPath.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - - // Need to add the string for escaped quotes around the path to the compiler. This is in case the path has spaces. - // Adding just quotes (escaped) doesn't work because this cmd line is used to execute another process. - AZStd::string insertPattern = "\\\""; - - // Search for the next space until that path exists. Then we assume that's the path to the executable. - size_t startPos = command.find(compilerPath.Native()); - for (size_t pos = command.find(" ", startPos); pos != AZStd::string::npos; pos = command.find(" ", pos + 1)) - { - if (AZ::IO::SystemFile::Exists(command.substr(startPos, pos - startPos).c_str())) - { - command.insert(pos, insertPattern); - command.insert(startPos, insertPattern); - } - } - } - else - { - command = AZStd::move(AZStd::string::format(pCompileFlags, pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - - command = compilerPath.Native() + command; - } - - AZStd::string hardwareTarget; - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) - #if defined(TOOLS_SUPPORT_JASPER) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, jasper) - #endif - #if defined(TOOLS_SUPPORT_PROVO) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, provo) - #endif - #if defined(TOOLS_SUPPORT_SALEM) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, salem) - #endif -#endif - - int64_t t0 = g_Timer.GetTime(); - - std::string outError; - - std::string shaderName; - std::stringstream crcStringStream; - - - // Dump source shader - if (SEnviropment::Instance().m_DumpShaders) - { - unsigned long crc = crc32(0l, Z_NULL, 0); - // shader permutations start with '(' - size_t position = strippedShaderRequestLine.find('('); - // split the string into shader name - shaderName = strippedShaderRequestLine.substr(0, position); - // split the string into permutation - std::string permutation = strippedShaderRequestLine.substr(position, strippedShaderRequestLine.length() - position); - // replace illegal filename characters with valid ones - AZStd::replace(shaderName.begin(), shaderName.end(), '<', '('); - AZStd::replace(shaderName.begin(), shaderName.end(), '>', ')'); - AZStd::replace(shaderName.begin(), shaderName.end(), '/', '_'); - AZStd::replace(shaderName.begin(), shaderName.end(), '|', '+'); - AZStd::replace(shaderName.begin(), shaderName.end(), '*', '^'); - AZStd::replace(shaderName.begin(), shaderName.end(), ':', ';'); - AZStd::replace(shaderName.begin(), shaderName.end(), '?', '!'); - AZStd::replace(shaderName.begin(), shaderName.end(), '%', '$'); - - crc = crc32(crc, reinterpret_cast(permutation.c_str()), static_cast(permutation.length())); - crcStringStream << crc; - const std::string HlslDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".hlsl"; - CSTLHelper::ToFile(HlslDump, std::vector(pProgram, &pProgram[strlen(pProgram)])); - std::ofstream crcFile; - - std::string crcFileName = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".txt"; - - crcFile.open(crcFileName, std::ios_base::trunc); - - if (!crcFile.fail()) - { - // store permutation - crcFile << permutation; - } - else - { - std::cout << "Error opening file " + crcFileName << std::endl; - } - - crcFile.close(); - } - - if (SEnviropment::Instance().m_PrintCommands) - { - AZ_Printf(0, "Compiler Command:\n%s\n\n", command.c_str()); - } - - if (!ExecuteCommand(command.c_str(), outError)) - { - unsigned char* nIP = (unsigned char*) &RequestIP(); - char sIP[128]; - azsprintf(sIP, "%d.%d.%d.%d", nIP[0], nIP[1], nIP[2], nIP[3]); - - const char* pProject = pElement->Attribute("Project"); - const char* pTags = pElement->Attribute("Tags"); - const char* pEmailCCs = pElement->Attribute("EmailCCs"); - - std::string project = pProject ? pProject : "Unk/"; - std::string ccs = pEmailCCs ? pEmailCCs : ""; - std::string tags = pTags ? pTags : ""; - - std::string filteredError; - AZ::IO::Path patchFilePath = TmpIn; - patchFilePath.ReplaceFilename(AZ::IO::PathView{ AZStd::string{ TmpIn.Filename().Native() } + ".patched" }); - CSTLHelper::Replace(filteredError, outError, patchFilePath.c_str(), "%filename%"); // DXPS does its own patching - CSTLHelper::Replace(filteredError, filteredError, TmpIn.c_str(), "%filename%"); - // replace any that don't have the full path - CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In.patched").c_str(), "%filename%"); // DXPS does its own patching - CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In").c_str(), "%filename%"); - - CSTLHelper::Replace(filteredError, filteredError, "\r\n", "\n"); - - State(ECSJS_ERROR_COMPILE); - throw new CCompilerError(pEntry, filteredError, ccs, sIP, pShaderRequestLine, pProgram, project, platform.c_str(), compiler.c_str(), language.c_str(), tags, pProfile); - } - - if (!CSTLHelper::FromFile(TmpOut.c_str(), rVec)) - { - State(ECSJS_ERROR_FILEIO); - std::string errorString("Could not read: "); - errorString += std::string(TmpOut.c_str(), TmpOut.Native().size()); - CrySimple_ERROR(errorString.c_str()); - return false; - } - - // Dump cross-compiled shader - if (SEnviropment::Instance().m_DumpShaders) - { - AZStd::string fileExtension = language; - AZStd::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), tolower); - - std::string shaderDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + "." + fileExtension.c_str(); - CSTLHelper::ToFile(shaderDump, rVec); - } - - - int64_t t1 = g_Timer.GetTime(); - int64_t dt = t1 - t0; - m_GlobalCompileTime += dt; - - int millis = (int)(g_Timer.TimeToSeconds(dt) * 1000.0); - int secondsTotal = (int)g_Timer.TimeToSeconds(m_GlobalCompileTime); - logmessage("Compiled [%5dms|%8ds] (%s - %s - %s - %s) %s\n", millis, secondsTotal, platform.c_str(), compiler.c_str(), language.c_str(), pProfile, pEntry); - - if (hardwareTarget.empty()) - { - logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry); - } - else - { - logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry, hardwareTarget.c_str()); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -inline bool SortByLinenum(const std::pair& f1, const std::pair& f2) -{ - return f1.first < f2.first; -} - -CCompilerError::CCompilerError(const std::string& entry, const std::string& errortext, const std::string& ccs, const std::string& IP, - const std::string& requestLine, const std::string& program, const std::string& project, - const std::string& platform, const std::string& compiler, const std::string& language, const std::string& tags, const std::string& profile) - : ICryError(COMPILE_ERROR) - , m_entry(entry) - , m_errortext(errortext) - , m_IP(IP) - , m_program(program) - , m_project(project) - , m_platform(platform) - , m_compiler(compiler) - , m_language(language) - , m_tags(tags) - , m_profile(profile) - , m_uniqueID(0) -{ - m_requests.push_back(requestLine); - Init(); - - CSTLHelper::Tokenize(m_CCs, ccs, ";"); -} - -void CCompilerError::Init() -{ - while (!m_errortext.empty() && (m_errortext.back() == '\r' || m_errortext.back() == '\n')) - { - m_errortext.pop_back(); - } - - if (m_requests[0].size()) - { - m_shader = m_requests[0]; - size_t offs = m_shader.find('>'); - if (offs != std::string::npos) - { - m_shader.erase(0, m_shader.find('>') + 1); // remove <2> version - } - offs = m_shader.find('@'); - if (offs != std::string::npos) - { - m_shader.erase(m_shader.find('@')); // remove everything after @ - } - offs = m_shader.find('/'); - if (offs != std::string::npos) - { - m_shader.erase(m_shader.find('/')); // remove everything after / (used on xenon) - } - } - else - { - // default to entry function - m_shader = m_entry; - size_t len = m_shader.length(); - - // if it ends in ?S then trim those two characters - if (m_shader[len - 1] == 'S') - { - m_shader.pop_back(); - m_shader.pop_back(); - } - } - - std::vector lines; - CSTLHelper::Tokenize(lines, m_errortext, "\n"); - - for (uint32_t i = 0; i < lines.size(); i++) - { - std::string& line = lines[i]; - - if (line.substr(0, 5) == "error") - { - m_errors.push_back(std::pair(-1, line)); - m_hasherrors += line; - - continue; - } - - if (line.find(": error") == std::string::npos) - { - continue; - } - - if (line.substr(0, 10) != "%filename%") - { - continue; - } - - if (line[10] != '(') - { - continue; - } - - uint32_t c = 11; - - int linenum = 0; - { - bool ln = true; - while (c < line.length() && - ((line[c] >= '0' && line[c] <= '9') || line[c] == ',' || line[c] == '-') - ) - { - if (line[c] == ',') - { - ln = false; // reached column, don't save the value - just keep reading to the end - } - if (ln) - { - linenum *= 10; - linenum += line[c] - '0'; - } - c++; - } - - if (c >= line.length()) - { - continue; - } - - if (line[c] != ')') - { - continue; - } - - c++; - } - - while (c < line.length() && (line[c] == ' ' || line[c] == ':')) - { - c++; - } - - if (line.substr(c, 5) != "error") - { - continue; - } - - m_errors.push_back(std::pair(linenum, line)); - m_hasherrors += line.substr(c); - } - - AZStd::sort(m_errors.begin(), m_errors.end(), SortByLinenum); -} - -std::string CCompilerError::GetErrorLines() const -{ - std::string ret = ""; - - for (uint32_t i = 0; i < m_errors.size(); i++) - { - if (m_errors[i].first < 0) - { - ret += m_errors[i].second + "\n"; - } - else if (i > 0 && m_errors[i - 1].first < 0) - { - ret += "\n" + GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n"; - } - else if (i > 0 && m_errors[i - 1].first == m_errors[i].first) - { - ret.pop_back(); // pop extra newline - ret += m_errors[i].second + "\n\n"; - } - else - { - ret += GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n"; - } - } - - return ret; -} - -std::string CCompilerError::GetContext(int linenum, int context, std::string prefix) const -{ - std::vector lines; - CSTLHelper::Tokenize(lines, m_program, "\n"); - - std::string ret = ""; - - linenum--; // line numbers start at one - - char sLineNum[16]; - - for (uint32_t i = AZStd::GetMax(0U, (uint32_t)(linenum - context)); i <= AZStd::GetMin((uint32_t)lines.size() - 1U, (uint32_t)(linenum + context)); i++) - { - azsprintf(sLineNum, "% 3d", i + 1); - - ret += sLineNum; - ret += " "; - - if (prefix.size()) - { - if (i == linenum) - { - ret += "*"; - } - else - { - ret += " "; - } - - ret += prefix; - - ret += " "; - } - - ret += lines[i] + "\n"; - } - - return ret; -} - -void CCompilerError::AddDuplicate(ICryError* err) -{ - ICryError::AddDuplicate(err); - - if (err->GetType() == COMPILE_ERROR) - { - CCompilerError* comperr = (CCompilerError*)err; - m_requests.insert(m_requests.end(), comperr->m_requests.begin(), comperr->m_requests.end()); - } -} - -bool CCompilerError::Compare(const ICryError* err) const -{ - if (GetType() != err->GetType()) - { - return GetType() < err->GetType(); - } - - CCompilerError* e = (CCompilerError*)err; - - if (m_platform != e->m_platform) - { - return m_platform < e->m_platform; - } - - if (m_compiler != e->m_compiler) - { - return m_compiler < e->m_compiler; - } - - if (m_language != e->m_language) - { - return m_language < e->m_language; - } - - if (m_shader != e->m_shader) - { - return m_shader < e->m_shader; - } - - if (m_entry != e->m_entry) - { - return m_entry < e->m_entry; - } - - return Hash() < err->Hash(); -} - -bool CCompilerError::CanMerge(const ICryError* err) const -{ - if (GetType() != err->GetType()) // don't merge with non compile errors - { - return false; - } - - CCompilerError* e = (CCompilerError*)err; - - if (m_platform != e->m_platform || m_compiler != e->m_compiler || m_language != e->m_language || m_shader != e->m_shader) - { - return false; - } - - if (m_CCs.size() != e->m_CCs.size()) - { - return false; - } - - for (size_t a = 0, S = m_CCs.size(); a < S; a++) - { - if (m_CCs[a] != e->m_CCs[a]) - { - return false; - } - } - - return true; -} - -void CCompilerError::AddCCs(std::set& ccs) const -{ - for (size_t a = 0, S = m_CCs.size(); a < S; a++) - { - ccs.insert(m_CCs[a]); - } -} - -std::string CCompilerError::GetErrorName() const -{ - return std::string("[") + m_tags + "] Shader Compile Errors in " + m_shader + " on " + m_language + " for " + m_platform + " " + m_compiler; -} - -std::string CCompilerError::GetErrorDetails(EOutputFormatType outputType) const -{ - std::string errorString(""); - - char sUniqueID[16], sNumDuplicates[16]; - azsprintf(sUniqueID, "%d", m_uniqueID); - azsprintf(sNumDuplicates, "%d", NumDuplicates()); - - std::string errorOutput; - CSTLHelper::Replace(errorOutput, GetErrorLines(), "%filename%", std::string(sUniqueID) + "-" + GetFilename()); - - std::string fullOutput; - CSTLHelper::Replace(fullOutput, m_errortext, "%filename%", std::string(sUniqueID) + "-" + GetFilename()); - - if (outputType == OUTPUT_HASH) - { - errorString = GetFilename() + m_IP + m_platform + m_compiler + m_language + m_project + m_entry + m_tags + m_profile + m_hasherrors /*+ m_requestline*/; - } - else if (outputType == OUTPUT_EMAIL) - { - errorString = std::string("=== Shader compile error in ") + m_entry + " (" + sNumDuplicates + " duplicates)\n\n"; - - ///// - errorString += std::string("* From: ") + m_IP + " on " + m_language + " for " + m_platform + " " + m_compiler + " " + m_project; - if (m_tags != "") - { - errorString += std::string(" (Tags: ") + m_tags + ")"; - } - errorString += "\n"; - - ///// - errorString += std::string("* Target profile: ") + m_profile + "\n"; - - ///// - bool hasrequests = false; - for (uint32_t i = 0; i < m_requests.size(); i++) - { - if (m_requests[i].size()) - { - errorString += std::string("* Shader request line: ") + m_requests[i] + "\n"; - hasrequests = true; - } - } - - errorString += "\n"; - - if (hasrequests) - { - errorString += "* Shader source from first listed request\n"; - } - - errorString += std::string("* Reported error(s) from ") + sUniqueID + "-" + GetFilename() + "\n\n"; - errorString += errorOutput + "\n\n"; - - errorString += std::string("* Full compiler output:\n\n"); - errorString += fullOutput + "\n"; - } - else if (outputType == OUTPUT_TTY) - { - errorString = std::string("=== Shader compile error in ") + m_entry + " { " + m_requests[0] + " }\n"; - // errors only - errorString += std::string("* Reported error(s):\n\n"); - errorString += errorOutput; - errorString += m_errortext; - } - - return errorString; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp deleted file mode 100644 index 7f097cbd7c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE__ -#define __CRYSIMPLEJOBCOMPILE__ - -#include "CrySimpleJobCache.hpp" -#include -#include - - -class CCrySimpleJobCompile - : public CCrySimpleJobCache -{ -public: - CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector* pRVec); - virtual ~CCrySimpleJobCompile(); - - virtual bool Execute(const TiXmlElement* pElement); - - static long GlobalCompileTasks(){return m_GlobalCompileTasks; } - static long GlobalCompileTasksMax(){return m_GlobalCompileTasksMax; } - -private: - static AZStd::atomic_long m_GlobalCompileTasks; - static AZStd::atomic_long m_GlobalCompileTasksMax; - static volatile int32_t m_RemoteServerID; - static volatile int64_t m_GlobalCompileTime; - - EProtocolVersion m_Version; - std::vector* m_pRVec; - - virtual size_t SizeOf(std::vector& rVec) = 0; - - bool Compile(const TiXmlElement* pElement, std::vector& rVec); -}; - -class CCompilerError - : public ICryError -{ -public: - CCompilerError(const std::string& entry, const std::string& errortext, const std::string& ccs, const std::string& IP, - const std::string& requestLine, const std::string& program, const std::string& project, - const std::string& platform, const std::string& compiler, const std::string& language, const std::string& tags, const std::string& profile); - - virtual ~CCompilerError() {} - - virtual void AddDuplicate(ICryError* err); - - virtual void SetUniqueID(int uniqueID) { m_uniqueID = uniqueID; } - - virtual bool Compare(const ICryError* err) const; - virtual bool CanMerge(const ICryError* err) const; - - virtual bool HasFile() const { return true; } - - virtual void AddCCs(std::set& ccs) const; - - virtual std::string GetErrorName() const; - virtual std::string GetErrorDetails(EOutputFormatType outputType) const; - virtual std::string GetFilename() const { return m_entry + ".txt"; } - virtual std::string GetFileContents() const { return m_program; } - - std::vector m_requests; -private: - void Init(); - std::string GetErrorLines() const; - std::string GetContext(int linenum, int context = 2, std::string prefix = ">") const; - - std::vector< std::pair > m_errors; - - tdEntryVec m_CCs; - - std::string m_entry, m_errortext, m_hasherrors, m_IP, - m_program, m_project, m_shader, - m_platform, m_compiler, m_language, m_tags, m_profile; - int m_uniqueID; - - friend CCompilerError; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp deleted file mode 100644 index 35582a64cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include -#include -#include -#include -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile1.hpp" - - - -CCrySimpleJobCompile1::CCrySimpleJobCompile1(uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJobCompile(requestIP, EPV_V001, pRVec) -{ -} - -size_t CCrySimpleJobCompile1::SizeOf(std::vector& rVec) -{ - return rVec.size(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp deleted file mode 100644 index 839ab2f393..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE1__ -#define __CRYSIMPLEJOBCOMPILE1__ - -#include "CrySimpleJobCompile.hpp" - - -class CCrySimpleJobCompile1 - : public CCrySimpleJobCompile -{ - virtual size_t SizeOf(std::vector& rVec); - -public: - CCrySimpleJobCompile1(uint32_t requestIP, std::vector* pRVec); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp deleted file mode 100644 index 4946f7146b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile2.hpp" - -#include -#include -#include -#include - - - -CCrySimpleJobCompile2::CCrySimpleJobCompile2(EProtocolVersion version, uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJobCompile(requestIP, version, pRVec) -{ -} - -size_t CCrySimpleJobCompile2::SizeOf(std::vector& rVec) -{ - const char* pXML = reinterpret_cast(&rVec[0]); - const char* pFirst = strstr(pXML, "HashStop"); - return pFirst ? pFirst - pXML : rVec.size(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp deleted file mode 100644 index 6d52d9a822..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE2__ -#define __CRYSIMPLEJOBCOMPILE2__ - -#include "CrySimpleJobCompile.hpp" - - -class CCrySimpleJobCompile2 - : public CCrySimpleJobCompile -{ - virtual size_t SizeOf(std::vector& rVec); - -public: - CCrySimpleJobCompile2(EProtocolVersion version, uint32_t requestIP, std::vector* pRVec); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp deleted file mode 100644 index b0c87edf90..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "CrySimpleJobGetShaderList.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - - -CCrySimpleJobGetShaderList::CCrySimpleJobGetShaderList(uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJob(requestIP) - , m_pRVec(pRVec) -{ -} - -bool CCrySimpleJobGetShaderList::Execute(const TiXmlElement* pElement) -{ - AZ::IO::Path shaderListFilename; - - const char* project = pElement->Attribute("Project"); - const char* shaderList = pElement->Attribute("ShaderList"); - const char* platform = pElement->Attribute("Platform"); - const char* compiler = pElement->Attribute("Compiler"); - const char* language = pElement->Attribute("Language"); - - shaderListFilename = project; - shaderListFilename /= "Cache"; - shaderListFilename /= AZStd::string::format("%s-%s-%s", platform, compiler, language); - shaderListFilename /= shaderList; - - //open the file and read into the rVec - - FILE* pFile = nullptr; - azfopen(&pFile, shaderListFilename.c_str(), "rb"); - if (!pFile) - { - // Fake a good result. We can't be sure if this file name is bad or if it doesn't exist *yet*, so we'll just assume the latter. - m_pRVec->resize(4, '\0'); - State(ECSJS_DONE); - return true; - } - - fseek(pFile, 0, SEEK_END); - size_t fileSize = ftell(pFile); - m_pRVec->resize(fileSize); - fseek(pFile, 0, SEEK_SET); - - size_t remaining = fileSize; - size_t read = 0; - while (remaining) - { - read += fread(m_pRVec->data() + read, 1, remaining, pFile); - remaining -= read; - } - - fclose(pFile); - - //compress before sending - tdDataVector rDataRaw; - rDataRaw.swap(*m_pRVec); - if (!CSTLHelper::Compress(rDataRaw, *m_pRVec)) - { - State(ECSJS_ERROR_COMPRESS); - CrySimple_ERROR("failed to compress request"); - return false; - } - State(ECSJS_DONE); - - return true; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp deleted file mode 100644 index 58f2ac16c7..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp +++ /dev/null @@ -1,29 +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. -* -*/ - -#ifndef __CRYSIMPLEJOBGETSHADERLIST__ -#define __CRYSIMPLEJOBGETSHADERLIST__ - -#include "CrySimpleJob.hpp" - - -class CCrySimpleJobGetShaderList - : public CCrySimpleJob -{ -public: - CCrySimpleJobGetShaderList(uint32_t requestIP, std::vector* pRVec); - - virtual bool Execute(const TiXmlElement* pElement); - std::vector* m_pRVec = nullptr; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp deleted file mode 100644 index 878d8921dd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJobRequest.hpp" -#include "CrySimpleServer.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -CCrySimpleJobRequest::CCrySimpleJobRequest(EProtocolVersion Version, uint32_t requestIP) - : CCrySimpleJob(requestIP) - , m_Version(Version) -{ -} - -bool CCrySimpleJobRequest::Execute(const TiXmlElement* pElement) -{ - const char* shaderRequest = pElement->Attribute("ShaderRequest"); - if (!shaderRequest) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("Missing shader request line"); - return false; - } - - AZ::IO::Path shaderListFilename; - if (m_Version >= EPV_V0023) - { - const char* project = pElement->Attribute("Project"); - const char* shaderList = pElement->Attribute("ShaderList"); - if (!project) - { - State(ECSJS_ERROR_INVALID_PROJECT); - CrySimple_ERROR("Missing Project for shader request"); - return false; - } - if (!shaderList) - { - State(ECSJS_ERROR_INVALID_SHADERLIST); - CrySimple_ERROR("Missing Shader List for shader request"); - return false; - } - - // NOTE: These attributes were alredy validated. - AZStd::string platform = pElement->Attribute("Platform"); - AZStd::string compiler = pElement->Attribute("Compiler"); - AZStd::string language = pElement->Attribute("Language"); - - shaderListFilename = project; - shaderListFilename /= "Cache"; - shaderListFilename /= AZStd::string::format("%s-%s-%s", platform.c_str(), compiler.c_str(), language.c_str()); - shaderListFilename /= shaderList; - } - else - { - // In previous versions Platform attribute is the shader list filename directly - shaderListFilename = pElement->Attribute("Platform"); - } - - std::string shaderRequestLine(shaderRequest); - tdEntryVec toks; - CSTLHelper::Tokenize(toks, shaderRequestLine, ";"); - for (size_t a = 0, s = toks.size(); a < s; a++) - { - CShaderList::Instance().Add(shaderListFilename.c_str(), toks[a].c_str()); - } - - State(ECSJS_DONE); - - return true; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp deleted file mode 100644 index f55334a1da..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBREQUEST__ -#define __CRYSIMPLEJOBREQUEST__ - -#include "CrySimpleJob.hpp" -#include "CrySimpleSock.hpp" - - -class CCrySimpleJobRequest - : public CCrySimpleJob -{ -public: - CCrySimpleJobRequest(EProtocolVersion Version, uint32_t requestIP); - - virtual bool Execute(const TiXmlElement* pElement); - -private: - EProtocolVersion m_Version; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp deleted file mode 100644 index 997d2fe9b0..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleMutex.hpp" - -#include -#include -#include - - -CCrySimpleMutex::CCrySimpleMutex() -{ -#if defined(AZ_PLATFORM_WINDOWS) - InitializeCriticalSectionAndSpinCount(&cs, 10000); -#else - pthread_mutex_init(&m_Mutex, nullptr); -#endif -} - -CCrySimpleMutex::~CCrySimpleMutex() -{ -#if defined(AZ_PLATFORM_WINDOWS) - DeleteCriticalSection(&cs); -#else - pthread_mutex_destroy(&m_Mutex); -#endif -} - - -void CCrySimpleMutex::Lock() -{ -#if defined(AZ_PLATFORM_WINDOWS) - EnterCriticalSection(&cs); -#else - pthread_mutex_lock(&m_Mutex); -#endif -} - -void CCrySimpleMutex::Unlock() -{ -#if defined(AZ_PLATFORM_WINDOWS) - LeaveCriticalSection(&cs); -#else - pthread_mutex_unlock(&m_Mutex); -#endif -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp deleted file mode 100644 index 09aa08349d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEMUTEX__ -#define __CRYSIMPLEMUTEX__ - -#include - -#if !defined(AZ_PLATFORM_WINDOWS) -#include "pthread.h" -#endif - -class CCrySimpleMutex -{ -#if defined(AZ_PLATFORM_WINDOWS) - CRITICAL_SECTION cs; -#else - // Use posix thread support - pthread_mutex_t m_Mutex; -#endif -public: - CCrySimpleMutex(); - ~CCrySimpleMutex(); - - void Lock(); - void Unlock(); -}; - -class CCrySimpleMutexAutoLock -{ - CCrySimpleMutex& m_rMutex; -public: - CCrySimpleMutexAutoLock(CCrySimpleMutex& rMutex) - : m_rMutex(rMutex) - { - rMutex.Lock(); - } - ~CCrySimpleMutexAutoLock() - { - m_rMutex.Unlock(); - } -}; -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp deleted file mode 100644 index ede23c97fc..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp +++ /dev/null @@ -1,722 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include -#include -#include - -#include "CrySimpleServer.hpp" -#include "CrySimpleSock.hpp" -#include "CrySimpleJob.hpp" -#include "CrySimpleJobCompile1.hpp" -#include "CrySimpleJobCompile2.hpp" -#include "CrySimpleJobRequest.hpp" -#include "CrySimpleJobGetShaderList.hpp" -#include "CrySimpleCache.hpp" -#include "CrySimpleErrorLog.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#undef AZ_RESTRICTED_SECTION -#define CRYSIMPLESERVER_CPP_SECTION_1 1 -#define CRYSIMPLESERVER_CPP_SECTION_2 2 -#endif - -#if defined(AZ_PLATFORM_MAC) -#include -#include -#endif - -#include -#include -#include -#include - - -#ifdef WIN32 - #define EXTENSION ".exe" -#else - #define EXTENSION "" -#endif - -AZStd::atomic_long CCrySimpleServer::ms_ExceptionCount = {0}; - -static const bool autoDeleteJobWhenDone = true; -static const int sleepTimeWhenWaiting = 10; - -static AZStd::atomic_long g_ConnectionCount = {0}; - -SEnviropment* SEnviropment::m_instance=nullptr; - -void SEnviropment::Create() -{ - if (!m_instance) - { - m_instance = new SEnviropment; - } -} - -void SEnviropment::Destroy() -{ - if (m_instance) - { - delete m_instance; - m_instance = nullptr; - } -} - -SEnviropment& SEnviropment::Instance() -{ - AZ_Assert(m_instance, "Using SEnviropment::Instance() before calling SEnviropment::Create()"); - return *m_instance; -} - -// Shader Compilers ID -// NOTE: Values must be in sync with CShaderSrv::GetShaderCompilerName() function in the engine side. -const char* SEnviropment::m_Orbis_DXC = "Orbis_DXC"; -const char* SEnviropment::m_Jasper_FXC = "Jasper_FXC"; -const char* SEnviropment::m_D3D11_FXC = "D3D11_FXC"; -const char* SEnviropment::m_GLSL_HLSLcc = "GLSL_HLSLcc"; -const char* SEnviropment::m_METAL_HLSLcc = "METAL_HLSLcc"; -const char* SEnviropment::m_GLSL_LLVM_DXC = "GLSL_LLVM_DXC"; -const char* SEnviropment::m_METAL_LLVM_DXC = "METAL_LLVM_DXC"; - -void SEnviropment::InitializePlatformAttributes() -{ - // Initialize valid Plaforms - // NOTE: Values must be in sync with CShaderSrv::GetPlatformName() function in the engine side. - m_Platforms.insert("Orbis"); - m_Platforms.insert("Nx"); - m_Platforms.insert("PC"); - m_Platforms.insert("Mac"); - m_Platforms.insert("iOS"); - m_Platforms.insert("Android"); - m_Platforms.insert("Linux"); - m_Platforms.insert("Jasper"); - - // Initialize valid Shader Languages - // NOTE: Values must be in sync with GetShaderLanguageName() function in the engine side. - m_ShaderLanguages.insert("Orbis"); - m_ShaderLanguages.insert("D3D11"); - m_ShaderLanguages.insert("METAL"); - m_ShaderLanguages.insert("GL4"); - m_ShaderLanguages.insert("GLES3"); - m_ShaderLanguages.insert("Jasper"); - // These are added for legacy support (GLES3_0 and GLES3_1 are combined into just GLES3) - m_ShaderLanguages.insert("GL4_1"); - m_ShaderLanguages.insert("GL4_4"); - m_ShaderLanguages.insert("GLES3_0"); - m_ShaderLanguages.insert("GLES3_1"); - - // Initialize valid Shader Compilers ID and Executables. - // Intentionally put a space after the executable name so that attackers can't try to change the executable name that we are going to run. -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#if defined(TOOLS_SUPPORT_JASPER) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, jasper) -#endif -#if defined(TOOLS_SUPPORT_PROVO) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, provo) -#endif -#if defined(TOOLS_SUPPORT_SALEM) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, salem) -#endif -#endif - - m_ShaderCompilersMap[m_D3D11_FXC] = "PCD3D11/v006/fxc.exe "; - m_ShaderCompilersMap[m_GLSL_HLSLcc] = "PCGL/V006/HLSLcc "; - m_ShaderCompilersMap[m_METAL_HLSLcc] = "PCGMETAL/HLSLcc/HLSLcc "; -#if defined(_DEBUG) - m_ShaderCompilersMap[m_GLSL_LLVM_DXC] = "LLVMGL/debug/dxcGL "; - m_ShaderCompilersMap[m_METAL_LLVM_DXC] = "LLVMMETAL/debug/dxcMetal "; -#else - m_ShaderCompilersMap[m_GLSL_LLVM_DXC] = "LLVMGL/release/dxcGL "; - m_ShaderCompilersMap[m_METAL_LLVM_DXC] = "LLVMMETAL/release/dxcMetal "; -#endif -} - -bool SEnviropment::IsPlatformValid( const AZStd::string& platform ) const -{ - return m_Platforms.find(platform) != m_Platforms.end(); -} - -bool SEnviropment::IsShaderLanguageValid( const AZStd::string& shaderLanguage ) const -{ - return m_ShaderLanguages.find(shaderLanguage) != m_ShaderLanguages.end(); -} - -bool SEnviropment::IsShaderCompilerValid( const AZStd::string& shaderCompilerID ) const -{ - bool validCompiler = (m_ShaderCompilersMap.find(shaderCompilerID) != m_ShaderCompilersMap.end()); - - // Extra check for Mac: Only GL_LLVM_DXC and METAL_LLVM_DXC compilers are supported. - #if defined(AZ_PLATFORM_MAC) - if (validCompiler && - shaderCompilerID != m_GLSL_LLVM_DXC && - shaderCompilerID != m_METAL_LLVM_DXC) - { - printf("error: trying to use an unsupported compiler on Mac.\n"); - return false; - } - #endif - - return validCompiler; -} - -bool SEnviropment::GetShaderCompilerExecutable( const AZStd::string& shaderCompilerID, AZStd::string& shaderCompilerExecutable ) const -{ - auto it = m_ShaderCompilersMap.find(shaderCompilerID); - if (it != m_ShaderCompilersMap.end()) - { - shaderCompilerExecutable = it->second; - return true; - } - else - { - return false; - } -} - -class CThreadData -{ - uint32_t m_Counter; - CCrySimpleSock* m_pSock; -public: - CThreadData(uint32_t Counter, CCrySimpleSock* pSock) - : m_Counter(Counter) - , m_pSock(pSock){} - - ~CThreadData(){delete m_pSock; } - - CCrySimpleSock* Socket(){return m_pSock; } - uint32_t ID() const{return m_Counter; } -}; - -////////////////////////////////////////////////////////////////////////// - -bool CopyFileOnPlatform(const char* nameOfFileToCopy, const char* copiedFileName, bool failIfFileExists) -{ - if (AZ::IO::SystemFile::Exists(copiedFileName) && failIfFileExists) - { - AZ_Warning("CrySimpleServer", false, ("File to copy to, %s, already exists."), copiedFileName); - return false; - } - - AZ::IO::SystemFile fileToCopy; - if (!fileToCopy.Open(nameOfFileToCopy, AZ::IO::SystemFile::SF_OPEN_READ_ONLY)) - { - AZ_Warning("CrySimpleServer", false, ("Unable to open file: %s for copying."), nameOfFileToCopy); - return false; - } - - AZ::IO::SystemFile::SizeType fileLength = fileToCopy.Length(); - - AZ::IO::SystemFile newFile; - if (!newFile.Open(copiedFileName, AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE)) - { - AZ_Warning("CrySimpleServer", false, ("Unable to open new file: %s for copying."), copiedFileName); - return false; - } - - char* fileContents = new char[fileLength]; - fileToCopy.Read(fileLength, fileContents); - newFile.Write(fileContents, fileLength); - delete[] fileContents; - - return true; -} - -void MakeErrorVec(const std::string& errorText, tdDataVector& Vec) -{ - Vec.resize(errorText.size() + 1); - for (size_t i = 0; i < errorText.size(); i++) - { - Vec[i] = errorText[i]; - } - Vec[errorText.size()] = 0; - - // Compress output data - tdDataVector rDataRaw; - rDataRaw.swap(Vec); - if (!CSTLHelper::Compress(rDataRaw, Vec)) - { - Vec.resize(0); - } -} - -////////////////////////////////////////////////////////////////////////// -class CompileJob - : public AZ::Job -{ -public: - CompileJob() - : Job(autoDeleteJobWhenDone, nullptr) { } - void SetThreadData(CThreadData* threadData) { m_pThreadData.reset(threadData); } -protected: - void Process() override; - bool ValidatePlatformAttributes(EProtocolVersion Version, const TiXmlElement* pElement); -private: - std::unique_ptr m_pThreadData; -}; - -void CompileJob::Process() -{ - std::vector Vec; - std::unique_ptr Job; - EProtocolVersion Version = EPV_V001; - ECrySimpleJobState State = ECSJS_JOBNOTFOUND; - try - { - if (m_pThreadData->Socket()->Recv(Vec)) - { - std::string Request(reinterpret_cast(&Vec[0]), Vec.size()); - TiXmlDocument ReqParsed("Request.xml"); - ReqParsed.Parse(Request.c_str()); - - if (ReqParsed.Error()) - { - CrySimple_ERROR("failed to parse request XML"); - return; - } - const TiXmlElement* pElement = ReqParsed.FirstChildElement(); - if (!pElement) - { - CrySimple_ERROR("failed to extract First Element of the request"); - return; - } - - const char* pPing = pElement->Attribute("Identify"); - if (pPing) - { - const std::string& rData("ShaderCompilerServer"); - m_pThreadData->Socket()->Send(rData); - return; - } - - const char* pVersion = pElement->Attribute("Version"); - const char* pHardwareTarget = nullptr; - - //new request type? - if (pVersion) - { - if (std::string(pVersion) == "2.3") - { - Version = EPV_V0023; - } - else if (std::string(pVersion) == "2.2") - { - Version = EPV_V0022; - } - else if (std::string(pVersion) == "2.1") - { - Version = EPV_V0021; - } - else if (std::string(pVersion) == "2.0") - { - Version = EPV_V002; - } - } - - - // If the job type is 'GetShaderList', then we dont need to perform a validation on the platform - // attributes, since the command doesnt use them, and the incoming request will not have 'compiler' or 'language' - // attributes. - const char* pJobType = pElement->Attribute("JobType"); - if ((!pJobType) || (azstricmp(pJobType,"GetShaderList")!=0)) - { - if (!ValidatePlatformAttributes(Version, pElement)) - { - return; - } - } - - if (Version >= EPV_V002) - { - const std::string JobType(pJobType); - - if (Version >= EPV_V0023) - { - pHardwareTarget = pElement->Attribute("HardwareTarget"); - } - - if (Version >= EPV_V0021) - { - m_pThreadData->Socket()->WaitForShutDownEvent(true); - } - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) - #if defined(TOOLS_SUPPORT_JASPER) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, jasper) - #endif - #if defined(TOOLS_SUPPORT_PROVO) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, provo) - #endif - #if defined(TOOLS_SUPPORT_SALEM) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, salem) - #endif -#endif - - if (pJobType) - { - if (JobType == "RequestLine") - { - Job = std::make_unique(Version, m_pThreadData->Socket()->PeerIP()); - Job->Execute(pElement); - State = Job->State(); - Vec.resize(0); - } - else - if (JobType == "Compile") - { - Job = std::make_unique(Version, m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - State = Job->State(); - } - else - if (JobType == "GetShaderList") - { - Job = std::make_unique(m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - State = Job->State(); - } - else - { - printf("\nRequested unkown job %s\n", pJobType); - } - } - else - { - printf("\nVersion 2.0 or higher but has no JobType tag\n"); - } - } - else - { - //legacy request - Version = EPV_V001; - Job = std::make_unique(m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - } - m_pThreadData->Socket()->Send(Vec, State, Version); - - if (Version >= EPV_V0021) - { - /* - // wait until message has been succesfully delived before shutting down the connection - if(!m_pThreadData->Socket()->RecvResult()) - { - printf("\nInvalid result from client\n"); - } - */ - } - } - } - catch (const ICryError* err) - { - CCrySimpleServer::IncrementExceptionCount(); - - CRYSIMPLE_LOG(" " + err->GetErrorName()); - - std::string returnStr = err->GetErrorDetails(ICryError::OUTPUT_TTY); - - // Send error back - MakeErrorVec(returnStr, Vec); - - if (Job.get()) - { - State = Job->State(); - - if (State == ECSJS_ERROR_COMPILE && SEnviropment::Instance().m_PrintErrors) - { - printf("\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); - printf("%s\n", err->GetErrorName().c_str()); - printf("%s\n", returnStr.c_str()); - printf("\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\n"); - } - } - - bool added = CCrySimpleErrorLog::Instance().Add((ICryError*)err); - - // error log hasn't taken ownership, delete this error. - if (!added) - { - delete err; - } - - m_pThreadData->Socket()->Send(Vec, State, Version); - } - --g_ConnectionCount; -} - - -bool CompileJob::ValidatePlatformAttributes(EProtocolVersion Version, const TiXmlElement* pElement) -{ - if (Version >= EPV_V0023) - { - const char* platform = pElement->Attribute("Platform"); // eg. PC, Mac... - const char* compiler = pElement->Attribute("Compiler"); // key to shader compiler executable - const char* language = pElement->Attribute("Language"); // eg. D3D11, GL4_1, GL3_1, METAL... - - if (!platform || !SEnviropment::Instance().IsPlatformValid(platform)) - { - CrySimple_ERROR("invalid Platform attribute from request."); - return false; - } - if (!compiler || !SEnviropment::Instance().IsShaderCompilerValid(compiler)) - { - CrySimple_ERROR("invalid Compiler attribute from request."); - return false; - } - if (!language || !SEnviropment::Instance().IsShaderLanguageValid(language)) - { - CrySimple_ERROR("invalid Language attribute from request."); - return false; - } - } - else - { - // In older versions the attribute Platform was used differently depending on the JobType - // - JobType Compile: Platform is the shader language - // - JobType RequestLine: Platform is the shader list filename - const char* platformLegacy = pElement->Attribute("Platform"); - - // The only check we can do here is if the attribute exists. Each JobType will check it has a valid value. - if (!platformLegacy) - { - CrySimple_ERROR("failed to extract required platform attribute from request."); - return false; - } - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void TickThread() -{ - AZ::u64 t0 = AZStd::GetTimeUTCMilliSecond(); - - while (true) - { - CrySimple_SECURE_START - - AZ::u64 t1 = AZStd::GetTimeUTCMilliSecond(); - if ((t1 < t0) || (t1 - t0 > 100)) - { - t0 = t1; - const int maxStringSize = 512; - char str[maxStringSize] = { 0 }; - azsnprintf(str, maxStringSize, "Amazon Shader Compiler Server (%ld compile tasks | %ld open sockets | %ld exceptions)", - CCrySimpleJobCompile::GlobalCompileTasks(), CCrySimpleSock::GetOpenSockets() + CSMTPMailer::GetOpenSockets(), - CCrySimpleServer::GetExceptionCount()); -#if defined(AZ_PLATFORM_WINDOWS) - SetConsoleTitle(str); -#endif - } - - const AZ::u64 T1 = AZStd::GetTimeUTCMilliSecond(); - CCrySimpleErrorLog::Instance().Tick(); - CShaderList::Instance().Tick(); - CCrySimpleCache::Instance().ThreadFunc_SavePendingCacheEntries(); - const AZ::u64 T2 = AZStd::GetTimeUTCMilliSecond(); - if (T2 - T1 < 100) - { - Sleep(static_cast(100 - T2 + T1)); - } - - CrySimple_SECURE_END - } -} - -////////////////////////////////////////////////////////////////////////// -void LoadCache() -{ - AZ::IO::Path cacheDatFile{ SEnviropment::Instance().m_CachePath }; - AZ::IO::Path cacheBakFile = cacheDatFile; - cacheDatFile /= "Cache.dat"; - cacheBakFile /= "Cache.bak"; - if (CCrySimpleCache::Instance().LoadCacheFile(cacheDatFile.c_str())) - { - AZ::IO::Path cacheBakFile2 = cacheBakFile; - cacheBakFile2.ReplaceFilename("Cache.bak2"); - - printf("Creating cache backup...\n"); - AZ::IO::SystemFile::Delete(cacheBakFile2.c_str()); - printf("Move %s to %s\n", cacheBakFile.c_str(), cacheBakFile2.c_str()); - AZ::IO::SystemFile::Rename(cacheBakFile.c_str(), cacheBakFile2.c_str()); - printf("Copy %s to %s\n", cacheDatFile.c_str(), cacheBakFile.c_str()); - CopyFileOnPlatform(cacheDatFile.c_str(), cacheBakFile.c_str(), false); - printf("Cache backup done.\n"); - } - else - { - // Restoring backup cache! - if (AZ::IO::SystemFile::Exists(cacheDatFile.c_str())) - { - printf("Cache file corrupted!!!\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - - printf("Restoring backup cache...\n"); - printf("Copy %s to %s\n", cacheBakFile.c_str(), cacheDatFile.c_str()); - CopyFileOnPlatform(cacheBakFile.c_str(), cacheDatFile.c_str(), false); - if (!CCrySimpleCache::Instance().LoadCacheFile(cacheDatFile.c_str())) - { - // Backup file corrupted too! - if (AZ::IO::SystemFile::Exists(cacheDatFile.c_str())) - { - printf("Backup file corrupted too!!!\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - printf("Deleting cache completely\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - } - - CCrySimpleCache::Instance().Finalize(); - printf("Ready\n"); -} - - -////////////////////////////////////////////////////////////////////////// -CCrySimpleServer::CCrySimpleServer([[maybe_unused]] const char* pShaderModel, [[maybe_unused]] const char* pDst, [[maybe_unused]] const char* pSrc, [[maybe_unused]] const char* pEntryFunction) - : m_pServerSocket(nullptr) -{ - Init(); -} - -CCrySimpleServer::CCrySimpleServer() - : m_pServerSocket(nullptr) -{ - CrySimple_SECURE_START - - uint32_t Port = SEnviropment::Instance().m_port; - - m_pServerSocket = new CCrySimpleSock(Port, SEnviropment::Instance().m_WhitelistAddresses); - Init(); - m_pServerSocket->Listen(); - - AZ::Job* tickThreadJob = AZ::CreateJobFunction(&TickThread, autoDeleteJobWhenDone); - tickThreadJob->Start(); - - uint32_t JobCounter = 0; - while (1) - { - // New client message, receive new client socket connection. - CCrySimpleSock* newClientSocket = m_pServerSocket->Accept(); - if(!newClientSocket) - { - continue; - } - - // Thread Data for new job - CThreadData* pData = new CThreadData(JobCounter++, newClientSocket); - - // Increase connection count and start new job. - // NOTE: CompileJob will be auto deleted when done, deleting thread data and client socket as well. - ++g_ConnectionCount; - CompileJob* compileJob = new CompileJob(); - compileJob->SetThreadData(pData); - compileJob->Start(); - - bool printedMessage = false; - while (g_ConnectionCount >= SEnviropment::Instance().m_MaxConnections) - { - if (!printedMessage) - { - logmessage("Waiting for a request to finish before accepting another connection...\n"); - printedMessage = true; - } - - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(sleepTimeWhenWaiting)); - }; - } - CrySimple_SECURE_END -} - -bool IsPathValid(const AZStd::string& path) -{ - return AZ::IO::PathView(path).IsRelativeTo(AZ::IO::PathView(SEnviropment::Instance().m_Root)); -} - -bool IsPathValid(const std::string& path) -{ - const AZStd::string tempString = path.c_str(); - return IsPathValid(tempString); -} - -void CCrySimpleServer::Init() -{ - SEnviropment::Instance().m_Root = AZ::Utils::GetExecutableDirectory(); - SEnviropment::Instance().m_CompilerPath = SEnviropment::Instance().m_Root / "Compiler"; - SEnviropment::Instance().m_CachePath = SEnviropment::Instance().m_Root / "Cache"; - - if (SEnviropment::Instance().m_TempPath.empty()) - { - SEnviropment::Instance().m_TempPath = SEnviropment::Instance().m_Root / "Temp"; - } - if (SEnviropment::Instance().m_ErrorPath.empty()) - { - SEnviropment::Instance().m_ErrorPath = SEnviropment::Instance().m_Root / "Error"; - } - if (SEnviropment::Instance().m_ShaderPath.empty()) - { - SEnviropment::Instance().m_ShaderPath = SEnviropment::Instance().m_Root / "Shaders"; - } - - SEnviropment::Instance().m_Root = SEnviropment::Instance().m_Root.LexicallyNormal(); - SEnviropment::Instance().m_CompilerPath = SEnviropment::Instance().m_CompilerPath.LexicallyNormal(); - SEnviropment::Instance().m_CachePath = SEnviropment::Instance().m_CachePath.LexicallyNormal(); - SEnviropment::Instance().m_ErrorPath = SEnviropment::Instance().m_ErrorPath.LexicallyNormal(); - SEnviropment::Instance().m_TempPath = SEnviropment::Instance().m_TempPath.LexicallyNormal(); - SEnviropment::Instance().m_ShaderPath = SEnviropment::Instance().m_ShaderPath.LexicallyNormal(); - - if (SEnviropment::Instance().m_Caching) - { - AZ::Job* loadCacheJob = AZ::CreateJobFunction(&LoadCache, autoDeleteJobWhenDone); - loadCacheJob->Start(); - } - else - { - printf("\nNO CACHING, disabled by config\n"); - } -} - -void CCrySimpleServer::IncrementExceptionCount() -{ - ++ms_ExceptionCount; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp deleted file mode 100644 index a7dcdb42ee..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLESERVER__ -#define __CRYSIMPLESERVER__ - -#include -#include -#include -#include -#include -#include -#include -#include - -extern bool g_Success; - - -bool IsPathValid(const AZStd::string& path); -bool IsPathValid(const std::string& path); - -namespace AZ { - class JobManager; -} - -class CCrySimpleSock; - -class SEnviropment -{ -public: - AZ::IO::Path m_Root; - AZ::IO::Path m_CompilerPath; - AZ::IO::Path m_CachePath; - AZ::IO::Path m_TempPath; - AZ::IO::Path m_ErrorPath; - AZ::IO::Path m_ShaderPath; - - std::string m_FailEMail; - std::string m_MailServer; - uint32_t m_port; - uint32_t m_MailInterval; // seconds since last error to flush error mails - - bool m_Caching; - bool m_PrintErrors = 1; - bool m_PrintWarnings; - bool m_PrintCommands; - bool m_PrintListUpdates; - bool m_DedupeErrors; - bool m_DumpShaders = false; - bool m_RunAsRoot = false; - std::string m_FallbackServer; - int32_t m_FallbackTreshold; - int32_t m_MaxConnections; - std::vector m_WhitelistAddresses; - - // Shader Compilers ID - static const char* m_Orbis_DXC; - static const char* m_Jasper_FXC; - static const char* m_D3D11_FXC; - static const char* m_GLSL_HLSLcc; - static const char* m_METAL_HLSLcc; - static const char* m_GLSL_LLVM_DXC; - static const char* m_METAL_LLVM_DXC; - - int m_hardwareTarget = -1; - - static void Create(); - static void Destroy(); - static SEnviropment& Instance(); - - void InitializePlatformAttributes(); - - bool IsPlatformValid( const AZStd::string& platform ) const; - bool IsShaderLanguageValid( const AZStd::string& shaderLanguage ) const; - bool IsShaderCompilerValid( const AZStd::string& shaderCompilerID ) const; - - bool GetShaderCompilerExecutable( const AZStd::string& shaderCompilerID, AZStd::string& shaderCompilerExecutable ) const; - -private: - SEnviropment() = default; - - // The single instance of the environment - static SEnviropment* m_instance; - - // Platforms - AZStd::unordered_set m_Platforms; - - // Shader Languages - AZStd::unordered_set m_ShaderLanguages; - - // Shader Compilers ID to Executable map - AZStd::unordered_map m_ShaderCompilersMap; -}; - -class CCrySimpleServer -{ - static AZStd::atomic_long ms_ExceptionCount; - CCrySimpleSock* m_pServerSocket; - void Init(); -public: - CCrySimpleServer(const char* pShaderModel, const char* pDst, const char* pSrc, const char* pEntryFunction); - CCrySimpleServer(); - - - static long GetExceptionCount() { return ms_ExceptionCount; } - static void IncrementExceptionCount(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp deleted file mode 100644 index e0cbd8d733..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleSock.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -#include -#include -#include -#include -#include -#else -#include -typedef int socklen_t; -#endif - -namespace -{ - enum ECrySimpleS_TYPE - { - ECrySimpleST_ROOT, - ECrySimpleST_SERVER, - ECrySimpleST_CLIENT, - ECrySimpleST_INVALID, - }; - - static AZStd::atomic_long numberOfOpenSockets = {0}; - const int MAX_DATA_SIZE = 1024 * 1024; // Only allow 1 MB of data to come through. Open 3D Engine has the same size constraint - const size_t BLOCKSIZE = 4 * 1024; - const size_t MAX_ERROR_MESSAGE_SIZE = 1024; - const size_t MAX_HOSTNAME_BUFFER_SIZE = 1024; - - struct Ip4WhitelistAddress - { - Ip4WhitelistAddress() : m_address(0), m_mask(-1) { } - // IP Address in network order to whitelist - uint32_t m_address; - // Mask in network order to apply to connecting IP addresses - uint32_t m_mask; - }; -} - -struct CCrySimpleSock::Implementation -{ - - Implementation(ECrySimpleS_TYPE type) - : m_Type(type) { } - - void SetWhitelist(const std::vector& whiteList) - { - // Add in our local address so that we always allow connections from the local machine - char hostNameBuffer[MAX_HOSTNAME_BUFFER_SIZE] = { 0 }; - gethostname(hostNameBuffer, MAX_HOSTNAME_BUFFER_SIZE); - struct addrinfo* addressInfos{}; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - int addressInfoResultCode = getaddrinfo(hostNameBuffer, nullptr, &hints, &addressInfos); - - if (addressInfoResultCode == 0) - { - int i = 0; - for (auto addressInfoIter = addressInfos; addressInfoIter != nullptr; addressInfoIter = addressInfoIter->ai_next) - { - Ip4WhitelistAddress whitelistAddress; - whitelistAddress.m_address = static_cast(reinterpret_cast(addressInfoIter->ai_addr)->sin_addr.s_addr); - m_ipWhiteList.push_back(whitelistAddress); - ++i; - } - } - else - { - printf("Network error trying to get host computer local address. The host computer's local IP addresses will not be automatically whitelisted."); - } - - for (const auto& address : whiteList) - { - Ip4WhitelistAddress whitelistAddress; - AZStd::string::size_type maskLocation = address.rfind("/"); - if (maskLocation != AZStd::string::npos) - { - //x.x.x.x/0 is all addresses - // For CIDR that specify the network mask, mask out the address that is - // supplied here once instead of everytime we check the address during - // accept calls. - int mask = atoi(address.substr(maskLocation+1).c_str()); - if (mask == 0) - { - whitelistAddress.m_mask = 0; - whitelistAddress.m_address = 0; - - static bool warnOnce = true; - if (warnOnce) - { - warnOnce = false; - printf("\nWARNING: Attempting to run the CrySCompileServer authorizing every IP. This is a security risk and not recommended.\nPlease use a more restrictive whitelist in the config.ini file by not using netmask 0.\n\n"); - } - } - else - { - whitelistAddress.m_mask ^= (1 << (32 - mask)) - 1; - whitelistAddress.m_mask = htonl(whitelistAddress.m_mask); - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, address.substr(0, maskLocation).c_str(), &ipv4Address) == 1) - { - whitelistAddress.m_address = static_cast(ipv4Address.s_addr); - } - } - } - else - { - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, address.c_str(), &ipv4Address) == 1) - { - whitelistAddress.m_address = static_cast(ipv4Address.s_addr); - } - } - - m_ipWhiteList.push_back(whitelistAddress); - } - } - - CCrySimpleSock* m_pInstance; - - const ECrySimpleS_TYPE m_Type; - SOCKET m_Socket; - uint16_t m_Port; -#ifdef USE_WSAEVENTS - WSAEVENT m_Event; -#endif - bool m_WaitForShutdownEvent; - bool m_SwapEndian; - - bool m_bHasReceivedData; - bool m_bHasSendData; - - tdDataVector m_tempSendBuffer; - - std::vector m_ipWhiteList; -}; - -#if defined(AZ_PLATFORM_WINDOWS) -typedef BOOL (WINAPI * LPFN_DISCONNECTEX)(SOCKET, LPOVERLAPPED, DWORD, DWORD); -#define WSAID_DISCONNECTEX {0x7fda2e11, 0x8630, 0x436f, {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57} \ -} -#endif - -#ifdef USE_WSAEVENTS -CCrySimpleSock::CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance, WSAEVENT wsaEvent) -#else -CCrySimpleSock::CCrySimpleSock(SOCKET Sock, CCrySimpleSock * pInstance) -#endif - : m_pImpl(new Implementation(ECrySimpleST_SERVER)) -{ - #ifdef USE_WSAEVENTS - m_pImpl->m_Event = wsaEvent; - #endif - - m_pImpl->m_pInstance = pInstance; - m_pImpl->m_Socket = Sock; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = ~0; - - ++numberOfOpenSockets; - - InitClient(); -} - - -CCrySimpleSock::CCrySimpleSock(const std::string& rServerName, uint16_t Port) - : m_pImpl(new Implementation(ECrySimpleST_CLIENT)) -{ - m_pImpl->m_pInstance = nullptr; - m_pImpl->m_Socket = INVALID_SOCKET; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = Port; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - addr.sin_port = htons(Port); - const char* pHostName = rServerName.c_str(); - bool IP = true; - for (size_t a = 0, size = strlen(pHostName); a < size; a++) - { - IP &= (pHostName[a] >= '0' && pHostName[a] <= '9') || pHostName[a] == '.'; - } - if (IP) - { - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, pHostName, &ipv4Address) == 1) - { - addr.sin_addr = ipv4Address; - } - } - else - { - struct addrinfo* addressInfo{}; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - int addressInfoResultCode = getaddrinfo(pHostName, nullptr, &hints, &addressInfo); - if (addressInfoResultCode != 9) - { - return; - } - addr = *reinterpret_cast(addressInfo->ai_addr); - } - - m_pImpl->m_Socket = socket(AF_INET, SOCK_STREAM, 0); - - ++numberOfOpenSockets; - - int Err = connect(m_pImpl->m_Socket, (struct sockaddr*)&addr, sizeof addr); - if (Err < 0) - { - m_pImpl->m_Socket = INVALID_SOCKET; - } -} - -CCrySimpleSock::~CCrySimpleSock() -{ - Release(); -} - -CCrySimpleSock::CCrySimpleSock(uint16_t Port, const std::vector& ipWhiteList) - : m_pImpl(new Implementation(ECrySimpleST_ROOT)) -{ - m_pImpl->m_pInstance = nullptr; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = Port; - -#ifdef _MSC_VER - WSADATA Data; - m_pImpl->m_Socket = INVALID_SOCKET; - if (WSAStartup(MAKEWORD(2, 0), &Data)) - { - CrySimple_ERROR("Could not init root socket"); - return; - } -#endif - m_pImpl->SetWhitelist(ipWhiteList); - - m_pImpl->m_Socket = socket(AF_INET, SOCK_STREAM, 0); - if (INVALID_SOCKET == m_pImpl->m_Socket) - { - CrySimple_ERROR("Could not initialize basic server due to invalid socket"); - return; - } - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - int arg = 1; - setsockopt(m_pImpl->m_Socket, SOL_SOCKET, SO_KEEPALIVE, &arg, sizeof arg); - arg = 1; - setsockopt(m_pImpl->m_Socket, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof arg); -#endif - - sockaddr_in SockAddr; - memset(&SockAddr, 0, sizeof(sockaddr_in)); - SockAddr.sin_family = PF_INET; - SockAddr.sin_port = htons(Port); - if (bind(m_pImpl->m_Socket, (sockaddr*)&SockAddr, sizeof(sockaddr_in)) == SOCKET_ERROR) - { -#if defined(AZ_PLATFORM_WINDOWS) - AZ_Warning(0, false, "bind failed with error = %d", WSAGetLastError()); -#else - shutdown(m_pImpl->m_Socket, SHUT_RDWR); -#endif - closesocket(m_pImpl->m_Socket); - CrySimple_ERROR("Could not bind server socket. This can happen if there is another process running already that is using this port or antivirus software/firewall is blocking the port.\n"); - return; - } - - ++numberOfOpenSockets; -} - -void CCrySimpleSock::Listen() -{ - listen(m_pImpl->m_Socket, SOMAXCONN); -} - -void CCrySimpleSock::InitClient() -{ -} - -void CCrySimpleSock::Release() -{ - if (m_pImpl->m_Socket != INVALID_SOCKET) - { - // check if we have received and sended data but ignore that for the HTTP server - if ((!m_pImpl->m_bHasSendData || !m_pImpl->m_bHasReceivedData) && (!m_pImpl->m_pInstance || m_pImpl->m_pInstance->m_pImpl->m_Port != 80)) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "ERROR : closing socket without both receiving and sending data: receive: %d send: %d", - m_pImpl->m_bHasReceivedData, m_pImpl->m_bHasSendData); - CRYSIMPLE_LOG(acTmp); - } - -#ifdef USE_WSAEVENTS - if (m_pImpl->m_WaitForShutdownEvent) - { - // wait until client has shutdown its socket - DWORD nReturnCode = WSAWaitForMultipleEvents(1, &m_pImpl->m_Event, - FALSE, INFINITE, FALSE); - if ((nReturnCode != WSA_WAIT_FAILED) && (nReturnCode != WSA_WAIT_TIMEOUT)) - { - WSANETWORKEVENTS NetworkEvents; - WSAEnumNetworkEvents(m_pImpl->m_Socket, m_pImpl->m_Event, &NetworkEvents); - if (NetworkEvents.lNetworkEvents & FD_CLOSE) - { - int iErrorCode = NetworkEvents.iErrorCode[FD_CLOSE_BIT]; - if (iErrorCode != 0) - { - // error shutting down - } - } - } - } - - // shutdown the server side of the connection since no more data will be sent - shutdown(m_pImpl->m_Socket, SHUT_RDWR); - closesocket(m_pImpl->m_Socket); -#endif - -#if defined(AZ_PLATFORM_WINDOWS) - LPFN_DISCONNECTEX pDisconnectEx = NULL; - DWORD Bytes; - GUID guidDisconnectEx = WSAID_DISCONNECTEX; - WSAIoctl(m_pImpl->m_Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidDisconnectEx, - sizeof(GUID), &pDisconnectEx, sizeof(pDisconnectEx), &Bytes, NULL, NULL); - pDisconnectEx(m_pImpl->m_Socket, NULL, 0, 0); // retrieve this function pointer with WSAIoctl(WSAID_DISCONNECTEX). -#else - shutdown(m_pImpl->m_Socket, SHUT_RDWR); -#endif - closesocket(m_pImpl->m_Socket); - m_pImpl->m_Socket = INVALID_SOCKET; - --numberOfOpenSockets; - } - -#if defined(AZ_PLATFORM_WINDOWS) - switch (m_pImpl->m_Type) - { - case ECrySimpleST_ROOT: - WSACleanup(); - break; - case ECrySimpleST_SERVER: // Intentionally fall through - case ECrySimpleST_CLIENT: - break; - default: - CrySimple_ERROR("unknown SocketType Released"); - } -#endif -} - -CCrySimpleSock* CCrySimpleSock::Accept() -{ - if (m_pImpl->m_Type != ECrySimpleST_ROOT) - { - CrySimple_ERROR("called Accept on non root socket"); - return nullptr; - } - - while (true) - { - sockaddr_in connectingAddress; - int addressSize = sizeof(connectingAddress); - SOCKET Sock = accept(m_pImpl->m_Socket, reinterpret_cast(&connectingAddress), reinterpret_cast(&addressSize)); - if (Sock == INVALID_SOCKET) - { -#if defined(AZ_PLATFORM_MAC) - switch (errno) - { - case EINTR: - // OS X tends to get interupt calls on every other accept call - // so just ignore this particular error and try the accept call - // again. - continue; - default: - // Do nothing - all other errors are "real" and we should exit - break; - } -#endif - AZ_Warning(0, false, "Errno = %d", WSAGetLastError()); - CrySimple_ERROR("Accept recived invalid socket"); - return nullptr; - } - - bool allowConnection = false; - - for (const auto& ip4WhitelistAddress : m_pImpl->m_ipWhiteList) - { - if ((connectingAddress.sin_addr.s_addr & ip4WhitelistAddress.m_mask) == (ip4WhitelistAddress.m_address)) - { - allowConnection = true; - break; - } - } - - if (!allowConnection) - { - constexpr size_t ipAddressBufferSize = 17; - char ipAddressBuffer[ipAddressBufferSize]{}; - inet_ntop(AF_INET, &connectingAddress.sin_addr, ipAddressBuffer, ipAddressBufferSize); - printf("Warning: unauthorized IP %s trying to connect. If this IP is authorized please add it to the whitelist in the config.ini file\n", ipAddressBuffer); - closesocket(Sock); - continue; - } - - int arg = 1; - setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, sizeof arg); - - /* - // keep socket open for another 2 seconds until data has been fully send - LINGER linger; - int len = sizeof(LINGER); - linger.l_onoff = 1; - linger.l_linger = 2; - setsockopt(Sock, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof linger); - */ - -#ifdef USE_WSAEVENTS - WSAEVENT wsaEvent = WSACreateEvent(); - if (wsaEvent == WSA_INVALID_EVENT) - { - closesocket(Sock); - int Error = WSAGetLastError(); - CrySimple_ERROR("Couldn't create wsa event"); - return nullptr; - } - - int Status = WSAEventSelect(Sock, wsaEvent, FD_CLOSE); - if (Status == SOCKET_ERROR) - { - closesocket(Sock); - int Error = WSAGetLastError(); - CrySimple_ERROR("Couldn't create wsa event"); - return nullptr; - } - - return new CCrySimpleSock(Sock, this, wsaEvent); -#else - return new CCrySimpleSock(Sock, this); -#endif - } - - return nullptr; -} - -union CrySimpleRecvSize -{ - uint8_t m_Data8[8]; - uint64_t m_Data64; -}; - -static const int MAX_TIME_TO_WAIT = 10000; - -int CCrySimpleSock::Recv(char* acData, int len, int flags) -{ - int recived = SOCKET_ERROR; - int waitingtime = 0; - while (recived < 0) - { - recived = recv(m_pImpl->m_Socket, acData, len, flags); - if (recived == SOCKET_ERROR) - { - int WSAError = WSAGetLastError(); -#if defined(AZ_PLATFORM_WINDOWS) - if (WSAError == WSAEWOULDBLOCK) - { - // are we out of time - if (waitingtime > MAX_TIME_TO_WAIT) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Timeout on blocking. (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return recived; - } - - waitingtime += 5; - - // sleep a bit and try again - Sleep(5); - } - else -#endif - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Network error. (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return recived; - } - } - } - - return recived; -} - -bool CCrySimpleSock::Recv(std::vector& rVec) -{ - CrySimpleRecvSize size; - - int received = Recv(reinterpret_cast(&size.m_Data8[0]), 8, 0); - if (received != 8) - { -#if defined(AZ_PLATFORM_WINDOWS) - int WSAError = WSAGetLastError(); -#else - int WSAError = errno; -#endif - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Invalid size (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - return false; - } - - if (size.m_Data64 == 0) - { - int WSAError = WSAGetLastError(); - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Size of zero (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return false; - } - - if (size.m_Data64 > MAX_DATA_SIZE) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Size is greater than max support data size."); - CrySimple_ERROR(acTmp); - - return false; - } - - m_pImpl->m_SwapEndian = (size.m_Data64 >> 32) != 0; - if (m_pImpl->m_SwapEndian) - { - CSTLHelper::EndianSwizzleU64(size.m_Data64); - } - - rVec.clear(); - rVec.resize(static_cast(size.m_Data64)); - - for (uint32_t a = 0; a < size.m_Data64; ) - { - int read = Recv(reinterpret_cast(&rVec[a]), static_cast(size.m_Data64) - a, 0); - if (read <= 0) - { - int WSAError = WSAGetLastError(); - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving tcp-data (size: %d - Error Code: %i)", static_cast(size.m_Data64), WSAError); - CrySimple_ERROR(acTmp); - return false; - } - a += read; - } - - m_pImpl->m_bHasReceivedData = true; - - return true; -} - -bool CCrySimpleSock::RecvResult() -{ - CrySimpleRecvSize size; - if (recv(m_pImpl->m_Socket, reinterpret_cast(&size.m_Data8[0]), 8, 0) != 8) - { - CrySimple_ERROR("Error while receiving result"); - return false; - } - - return size.m_Data64 > 0; -} - - -void CCrySimpleSock::Forward(const std::vector& rVecIn) -{ - tdDataVector& rVec = m_pImpl->m_tempSendBuffer; - rVec.resize(rVecIn.size() + 8); - CrySimpleRecvSize& rHeader = *(CrySimpleRecvSize*)(&rVec[0]); - rHeader.m_Data64 = (uint32_t)rVecIn.size(); - memcpy(&rVec[8], &rVecIn[0], rVecIn.size()); - - CrySimpleRecvSize size; - size.m_Data64 = static_cast(rVec.size()); - for (uint64_t a = 0; a < size.m_Data64; a += BLOCKSIZE) - { - char* pData = reinterpret_cast(&rVec[(size_t)a]); - int nSendRes = send(m_pImpl->m_Socket, pData, std::min(static_cast(size.m_Data64 - a), BLOCKSIZE), 0); - if (nSendRes == SOCKET_ERROR) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send(forward) error: %d", nLastSendError); - } - } -} - - -bool CCrySimpleSock::Backward(std::vector& rVec) -{ - uint32_t size; - if (recv(m_pImpl->m_Socket, reinterpret_cast(&size), 4, 0) != 4) - { - CrySimple_ERROR("Error while receiving size of data"); - return false; - } - - rVec.clear(); - rVec.resize(static_cast(size)); - - for (uint32_t a = 0; a < size; ) - { - int read = recv(m_pImpl->m_Socket, reinterpret_cast(&rVec[a]), size - a, 0); - if (read <= 0) - { - CrySimple_ERROR("Error while receiving tcp-data"); - return false; - } - a += read; - } - return true; -} - -void CCrySimpleSock::Send(const std::vector& rVecIn, size_t state, EProtocolVersion version) -{ - const size_t offset = version == EPV_V001 ? 4 : 5; - tdDataVector& rVec = m_pImpl->m_tempSendBuffer; - rVec.resize(rVecIn.size() + offset); - if (rVecIn.size()) - { - *(uint32_t*)(&rVec[0]) = (uint32_t)rVecIn.size(); - memcpy(&rVec[offset], &rVecIn[0], rVecIn.size()); - } - - if (version >= EPV_V002) - { - rVec[4] = static_cast(state); - } - - if (m_pImpl->m_SwapEndian) - { - CSTLHelper::EndianSwizzleU32(*(uint32_t*)&rVec[0]); - } - - // send can fail, you must retry unsent parts. - size_t remainingBytes = rVec.size(); - const char* pData = reinterpret_cast(rVec.data()); - - while (remainingBytes != 0) - { - size_t sendThisRound = remainingBytes; - if (sendThisRound > BLOCKSIZE) - { - sendThisRound = BLOCKSIZE; - } - - int bytesActuallySent = send(m_pImpl->m_Socket, pData, static_cast(sendThisRound), 0); - if (bytesActuallySent < 0) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send error: %d", nLastSendError); - m_pImpl->m_bHasSendData = true; - return; - } - size_t actuallySent = static_cast(bytesActuallySent); - - remainingBytes -= actuallySent; - pData += actuallySent; - } - - m_pImpl->m_bHasSendData = true; -} - - -void CCrySimpleSock::Send(const std::string& rData) -{ - const size_t S = rData.size(); - - for (uint64_t a = 0; a < S; a += BLOCKSIZE) - { - const char* pData = &rData.c_str()[a]; - const int nSendRes = send(m_pImpl->m_Socket, pData, std::min(static_cast(S - a), BLOCKSIZE), 0); - if (nSendRes == SOCKET_ERROR) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send error: %d", nLastSendError); - } - else - { - m_pImpl->m_bHasSendData = true; - } - } -} - -uint32_t CCrySimpleSock::PeerIP() -{ - struct sockaddr_in addr; -#if defined(AZ_PLATFORM_WINDOWS) - int addr_size = sizeof(sockaddr_in); -#else - socklen_t addr_size = sizeof(sockaddr_in); -#endif - int nRes = getpeername(m_pImpl->m_Socket, (sockaddr*) &addr, &addr_size); - if (nRes == SOCKET_ERROR) - { - int nError = WSAGetLastError(); - logmessage("Socket getpeername error: %d", nError); - return 0; - } -#if defined(AZ_PLATFORM_WINDOWS) - return addr.sin_addr.S_un.S_addr; -#else - return addr.sin_addr.s_addr; -#endif -} - -bool CCrySimpleSock::Valid() const -{ - return m_pImpl->m_Socket != INVALID_SOCKET; -} - -void CCrySimpleSock::WaitForShutDownEvent(bool bValue) -{ - m_pImpl->m_WaitForShutdownEvent = bValue; -} - -long CCrySimpleSock::GetOpenSockets() -{ - return numberOfOpenSockets; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp deleted file mode 100644 index ef35f03c03..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLESOCK__ -#define __CRYSIMPLESOCK__ - -#include -#include - -#include -#include - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -typedef int SOCKET; -#define INVALID_SOCKET (-1) -#define SOCKET_ERROR (-1) -#include -#include -#include -#include -#define closesocket close -#else -#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS -#define _WINSOCK_DEPRECATED_NO_WARNINGS // till we swtich to in inet_pton and getaddrinfo -#endif -#include -#endif - -#include -#include - -//#define USE_WSAEVENTS - -enum EProtocolVersion -{ - EPV_V001, - EPV_V002, - EPV_V0021, - EPV_V0022, - EPV_V0023, -}; - -class CCrySimpleSock -{ -public: - - -#ifdef USE_WSAEVENTS - CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance, WSAEVENT wsaEvent); -#else - CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance); -#endif - CCrySimpleSock(const CCrySimpleSock&); - - CCrySimpleSock(const std::string& rServerName, uint16_t Port); - CCrySimpleSock(uint16_t Port, const std::vector& ipWhiteList); - - ~CCrySimpleSock(); - - void InitClient(); - void Release(); - - int Recv(char* acData, int len, int flags); - - void Listen(); - - - CCrySimpleSock* Accept(); - - bool Recv(std::vector& rVec); - bool RecvResult(); - - bool Backward(std::vector& rVec); - void Send(const std::vector& rVec, size_t State, EProtocolVersion Version); - void Forward(const std::vector& rVec); - - //used for HTML - void Send(const std::string& rData); - - uint32_t PeerIP(); - - bool Valid() const; - - void WaitForShutDownEvent(bool bValue); - - static long GetOpenSockets(); - - -private: - struct Implementation; - std::unique_ptr m_pImpl; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp deleted file mode 100644 index 5de6e64ae8..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "ShaderList.hpp" -#include -#include - -#include "CrySimpleServer.hpp" - -#include - -#include -#ifdef _MSC_VER -#include -#include -#endif -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -#include -#include -#include -#include -#endif - -static bool g_bSaveThread = false; - -CShaderList& CShaderList::Instance() -{ - static CShaderList g_Cache; - return g_Cache; -} - -////////////////////////////////////////////////////////////////////////// -CShaderList::CShaderList() -{ - m_lastTime = 0; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Tick() -{ -#if defined(AZ_PLATFORM_WINDOWS) - DWORD t = GetTickCount(); -#else - unsigned long t = time(nullptr)*1000; // Current time in milliseconds -#endif - if (t < m_lastTime || (t - m_lastTime) > 1000) //check every second - { - m_lastTime = t; - - Save(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Add(const std::string& rShaderListName, const char* pLine) -{ - tdShaderLists::iterator it; - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - it = m_ShaderLists.find(rShaderListName); - //not existing yet? - if (it == m_ShaderLists.end()) - { - CCrySimpleMutexAutoLock Lock2(m_Mutex2); //load/save mutex - m_ShaderLists[rShaderListName] = new CShaderListFile(rShaderListName); - it = m_ShaderLists.find(rShaderListName); - it->second->Load((SEnviropment::Instance().m_CachePath / AZStd::string_view{ rShaderListName.c_str(), rShaderListName.size() }).c_str()); - } - } - it->second->InsertLine(pLine); -} - - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Save() -{ - CCrySimpleMutexAutoLock Lock(m_Mutex2); //load/save mutex - for (tdShaderLists::iterator it = m_ShaderLists.begin(); it != m_ShaderLists.end(); ++it) - { - it->second->MergeNewLinesAndSave(); - } -} - -////////////////////////////////////////////////////////////////////////// -CShaderListFile::CShaderListFile(std::string ListName) -{ - m_bModified = false; - - m_listname = ListName; - - // some test cases - SMetaData MD; - assert(CheckSyntax("<1>watervolume@WaterVolumeOutofPS()()(0)(0)(0)(ps_2_0)", MD) == true); - assert(CheckSyntax("<1>Blurcloak@BlurCloakPS(%BUMP_MAP)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)(0)(0)(1)(ps_2_0)", MD) == true); - assert(CheckSyntax("<1>Burninglayer@BurnPS()(%_RT_ADDBLEND|%_RT_)HDR_MODE|%_RT_BUMP|%_RT_3DC)(0)(0)(0)(ps_2_0)", MD) == false); - assert(CheckSyntax("<1>Illum@IlluminationVS(%DIFFUSE|%SPECULAR|%BUMP_MAP|%VERTCOLORS|%STAT_BRANCHING)(%_RT_RAE_GEOMTERM)(101)(0)(0)(vs_2_0)", MD) == true); - - assert(CheckSyntax("<660><2>Cloth@Common_SG_VS()(%_RT_QUALITY|%_RT_SHAPEDEFORM|%_RT_SKELETON_SSD|%_RT_HW_PCF_COMPARE)(0)(0)(0)(VS)", MD) == true); - assert(CheckSyntax("<6452><2>ShadowMaskGen@FrustumClipVolumeVS()()(0)(0)(0)(VS)", MD) == true); - assert(CheckSyntax("<5604><2>ParticlesNoMat@ParticlePS()(%_RT_FOG|%_RT_AMBIENT|%_RT_ALPHABLEND|%_RT_QUALITY1)(0)(0)(0)(PS)", MD) == true); -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Reload() -{ - return Load(m_filename.c_str()); -} - -void CShaderListFile::CreatePath(const std::string& rPath) -{ - std::string Path = rPath; - CSTLHelper::Replace(Path, rPath, "\\", "/"); - tdEntryVec rToks; - CSTLHelper::Tokenize(rToks, Path, "/"); - - Path = ""; - for (size_t a = 0; a + 1 < rToks.size(); a++) - { - Path += rToks[a] + "/"; -#if defined(AZ_PLATFORM_WINDOWS) - _mkdir(Path.c_str()); -#else - mkdir(Path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); -#endif - } -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Load(const char* filename) -{ - CreatePath(filename); - printf("Loading ShaderList file: %s\n", filename); - m_filename = filename; - m_filenametmp = filename; - m_filenametmp += ".tmp"; - FILE* f = nullptr; - azfopen(&f, filename, "rt"); - if (!f) - { - return false; - } - - int nNumLines = 0; - m_entries.clear(); - char str[65535]; - while (fgets(str, sizeof(str), f) != NULL) - { - if (*str && InsertLineInternal(str)) - { - ++nNumLines; - } - } - fclose(f); - if (nNumLines == m_entries.size()) - { - m_bModified = false; - } - else - { - m_bModified = true; - } - - printf("Loaded %d combination for %s\n", nNumLines, filename); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Save() -{ - //not needed regarding timur, m_entries is just accessed by one thread - //CCrySimpleMutexAutoLock Lock(m_Mutex); - - CreatePath(m_filename); - if (m_filename.empty()) - { - return false; - } - - // write to tmp file - FILE* f = nullptr; - azfopen(&f, m_filenametmp.c_str(), "wt"); - if (!f) - { - return false; - } - for (Entries::iterator it = m_entries.begin(); it != m_entries.end(); ++it) - { - const char* str = it->first.c_str(); - if (it->second.m_Count == -1) - { - fprintf(f, "<%d>%s\n", it->second.m_Version, str); - } - else - { - fprintf(f, "<%d><%d>%s\n", it->second.m_Count, it->second.m_Version, str); - } - } - fclose(f); - - // first check if original file excists - f = nullptr; - azfopen(&f, m_filename.c_str(), "rt"); - if (f) - { - fclose(f); - - // remove original file (keep on trying until success - shadercompiler could currently be copying it for example) - int sleeptime = 0; - while (remove(m_filename.c_str())) - { - Sleep(100); - - sleeptime += 100; - if (sleeptime > 5000) - { - break; - } - } - } - - { - int sleeptime = 0; - while (rename(m_filenametmp.c_str(), m_filename.c_str())) - { - Sleep(100); - - sleeptime += 100; - if (sleeptime > 5000) - { - break; - } - } - } - - m_bModified = false; - return true; -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsHexNumberCharacter(const char c) -{ - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsDecNumberCharacter(const char c) -{ - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsNameCharacter(const char c) -{ - return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '@' || c == '/' || c == '%' || c == '_'; -} - -int shGetHex(const char* buf) -{ - if (!buf) - { - return 0; - } - int i = 0; - - azsscanf(buf, "%x", &i); - - return i; -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::CheckSyntax(const char* szLine, SMetaData& rMD, const char** sOutStr) -{ - assert(szLine); - if (!szLine) - { - return false; - } - - if (sOutStr) - { - *sOutStr = 0; - } - - // e.g. Blurcloak@BlurCloakPS(%BUMP_MAP|%SPECULAR)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)(0)(0)(0)(ps_2_0) - - const char* p = szLine; - - if (strlen(szLine) < 4) - { - return false; - } - - int Value0 = 0; - int Value1 = 0; - - if (*p != '<') - { - return false; - } - - char Last = 0; - while (IsDecNumberCharacter(Last = *++p)) - { - Value0 = Value0 * 10 + (Last - '0'); - } - - if (*p++ != '>') - { - return false; - } - - if (*p == '<') - { - while (IsDecNumberCharacter(Last = *++p)) - { - Value1 = Value1 * 10 + (Last - '0'); - } - - if (*p++ != '>') - { - return false; - } - - rMD.m_Version = Value1; - rMD.m_Count = Value0; - } - else - { - rMD.m_Version = Value0; - rMD.m_Count = -1; - } - - const char* pStart = p; - - // e.g. "Blurcloak@BlurCloakPS" - while (IsNameCharacter(*p++)) - { - ; - } - p--; - - // e.g. "(%BUMP_MAP|%SPECULAR)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)" - for (int i = 0; i < 2; ++i) - { - if (*p++ != '(') - { - return false; - } - while (true) - { - while (IsNameCharacter(*p++)) - { - ; - } - p--; - if (*p != '|') - { - break; - } - p++; - } - if (*p++ != ')') - { - return false; - } - } - - // e.g. "(0)(0)(0)" - for (int i = 0; i < 3; ++i) - { - if (*p++ != '(') - { - return false; - } - while (IsHexNumberCharacter(*p++)) - { - ; - } - p--; - if (*p++ != ')') - { - return false; - } - } - - // e.g. "(ps_2_0)" - if (*p++ != '(') - { - return false; - } - while (IsNameCharacter(*p++)) - { - ; - } - p--; - if (*p++ != ')') - { - return false; - } - - // Copy rest of the line. - if (sOutStr) - { - *sOutStr = pStart; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::InsertLine(const char* szLine) -{ - if (*szLine != 0) - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_newLines.push_back(szLine); - m_bModified = true; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::InsertLineInternal(const char* szLine) -{ - const char* szCorrectedLine = 0; - SMetaData MD; - if (CheckSyntax(szLine, MD, &szCorrectedLine)) - { - // Trim \n\r - char* s = const_cast(szCorrectedLine); - for (size_t p = strlen(s) - 1; p > 0; p--) - { - if (s[p] == '\n' || s[p] == '\r') - { - s[p] = '\0'; - } - else - { - break; - } - } - - if (szCorrectedLine) - { - Entries::iterator it = m_entries.find(szCorrectedLine); - if (it == m_entries.end()) - { - m_entries[szCorrectedLine] = MD; - m_bModified = true; - } - else - { - if (it->second.m_Version < MD.m_Version) - { - it->second = MD; - m_bModified = true; - } - else - if (it->second.m_Count < MD.m_Count) - { - it->second.m_Count = MD.m_Count; - m_bModified = true; - } - } - } - return true; - } - - - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::MergeNewLines() -{ - std::vector newLines; - - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - newLines.swap(m_newLines); - } - - m_bModified = false; - - if (newLines.empty()) - { - return; - } - - for (std::vector::iterator it = newLines.begin(); it != newLines.end(); ++it) - { - InsertLineInternal((*it).c_str()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::MergeNewLinesAndSave() -{ - if (m_bModified) - { - MergeNewLines(); - } - if (m_bModified) - { - if (SEnviropment::Instance().m_PrintListUpdates) - { - logmessage("Updating: %s\n", m_listname.c_str()); - } - Save(); - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp deleted file mode 100644 index f624581b5f..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __SHADERLIST__ -#define __SHADERLIST__ - -#include -#include -#include - -#include "CrySimpleMutex.hpp" - -#include -#include -#include - -class CShaderListFile -{ - ////////////////////////////////////////////////////////////////////////// - struct SMetaData - { - SMetaData() - : m_Version(0) - , m_Count(-1) - {} - int32_t m_Version; - int32_t m_Count; - }; - bool m_bModified; - std::string m_listname; - std::string m_filename; - std::string m_filenametmp; - typedef std::map Entries; - Entries m_entries; - std::vector m_newLines; - - CCrySimpleMutex m_Mutex; - - //do not copy -> not safe - CShaderListFile(const CShaderListFile&); - CShaderListFile& operator=(const CShaderListFile&); - -public: - CShaderListFile(std::string ListName); - - bool Load(const char* filename); - bool Save(); - bool Reload(); - bool IsModified() const { return m_bModified; } - - void InsertLine(const char* szLine); - void MergeNewLinesAndSave(); - -private: - void CreatePath(const std::string& rPath); - void MergeNewLines(); - // Returns: - // true - line was instered, false otherwise - bool InsertLineInternal(const char* szLine); - - // Returns - // true=syntax is ok, false=syntax is wrong - static bool CheckSyntax(const char* szLine, SMetaData& rMD, const char** sOutStr = NULL); -}; - -typedef std::map tdShaderLists; - -class CShaderList -{ - CCrySimpleMutex m_Mutex; - CCrySimpleMutex m_Mutex2; - unsigned long m_lastTime; - - tdShaderLists m_ShaderLists; - - void Save(); -public: - static CShaderList& Instance(); - CShaderList(); - - void Add(const std::string& rShaderListName, const char* pLine); - void Tick(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp deleted file mode 100644 index c505d91a51..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __STDTYPES_DUMMY__ -#define __STDTYPES_DUMMY__ - -#include - - -#if defined(AZ_PLATFORM_WINDOWS) -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef signed __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#endif - -#if defined(UNIX) -#include -#include "Core/UnixCompat.h" -#endif - -#if defined(AZ_PLATFORM_MAC) -#include -#endif - -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp deleted file mode 100644 index 8e23fcfb78..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "WindowsAPIImplementation.h" - -#if defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX) - -#include -#include -#import -#include - -bool QueryPerformanceCounter(LARGE_INTEGER* counter) -{ -#if defined(LINUX) - // replaced gettimeofday - // http://fixunix.com/kernel/378888-gettimeofday-resolution-linux.html - timespec tv; - clock_gettime(CLOCK_MONOTONIC, &tv); - counter->QuadPart = (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000; -#elif defined(APPLE) - counter->QuadPart = mach_absolute_time(); -#endif - return true; -} - -bool QueryPerformanceFrequency(LARGE_INTEGER* frequency) -{ -#if defined(LINUX) - // On Linux we'll use gettimeofday(). The API resolution is microseconds, - // so we'll report that to the caller. - frequency->u.LowPart = 1000000; - frequency->u.HighPart = 0; -#elif defined(APPLE) - static mach_timebase_info_data_t s_kTimeBaseInfoData; - if (s_kTimeBaseInfoData.denom == 0) - { - mach_timebase_info(&s_kTimeBaseInfoData); - } - // mach_timebase_info_data_t expresses the tick period in nanoseconds - frequency->QuadPart = 1e+9 * (uint64_t)s_kTimeBaseInfoData.denom / (uint64_t)s_kTimeBaseInfoData.numer; -#endif - return true; -} - -int WSAGetLastError() -{ - return errno; -} - -DWORD Sleep(DWORD dwMilliseconds) -{ - timespec req; - timespec rem; - - memset(&req, 0, sizeof(req)); - memset(&rem, 0, sizeof(rem)); - - time_t sec = (int)(dwMilliseconds / 1000); - req.tv_sec = sec; - req.tv_nsec = (dwMilliseconds - (sec * 1000)) * 1000000L; - if (nanosleep(&req, &rem) == -1) - { - nanosleep(&rem, 0); - } - - return 0; -} - - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h deleted file mode 100644 index 5879612917..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h +++ /dev/null @@ -1,78 +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 -#include - -#if defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX) -#include - -#ifndef MAX_PATH -#define MAX_PATH PATH_MAX -#endif - -typedef uint32_t DWORD; - -typedef union _LARGE_INTEGER -{ - struct - { - uint32_t LowPart; - int32_t HighPart; - }; - struct - { - uint32_t LowPart; - int32_t HighPart; - } u; - - int64_t QuadPart; -} LARGE_INTEGER; - -bool QueryPerformanceCounter(LARGE_INTEGER* counter); - -bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); - -int WSAGetLastError(); - -DWORD Sleep(DWORD dwMilliseconds); - -#if defined(AZ_PLATFORM_LINUX) - -namespace PthreadImplementation -{ - static pthread_mutex_t g_interlockMutex; -} - -template -const volatile T InterlockedIncrement(volatile T* pT) -{ - pthread_mutex_lock(&PthreadImplementation::g_interlockMutex); - ++(*pT); - pthread_mutex_unlock(&PthreadImplementation::g_interlockMutex); - return *pT; -} - -template -const volatile T InterlockedDecrement(volatile T* pT) -{ - pthread_mutex_lock(&PthreadImplementation::g_interlockMutex); - --(*pT); - pthread_mutex_unlock(&PthreadImplementation::g_interlockMutex); - return *pT; -} - -#endif - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp deleted file mode 100644 index cec8628d30..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "Core/StdTypes.hpp" -#include "Core/Server/CrySimpleServer.hpp" -#include "Core/Server/CrySimpleHTTP.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if AZ_TRAIT_OS_PLATFORM_APPLE -// Needed for geteuid() -#include -#include -#endif - -namespace -{ - const int STD_TCP_PORT = 61453; - const int DEFAULT_MAX_CONNECTIONS = 255; -} - -////////////////////////////////////////////////////////////////////////// -class CConfigFile -{ -public: - CConfigFile() {} - ////////////////////////////////////////////////////////////////////////// - void OnLoadConfigurationEntry(const std::string& strKey, const std::string& strValue, [[maybe_unused]] const std::string& strGroup) - { - if (azstricmp(strKey.c_str(), "MailError") == 0) - { - SEnviropment::Instance().m_FailEMail = strValue; - } - if (azstricmp(strKey.c_str(), "port") == 0) - { - SEnviropment::Instance().m_port = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "MailInterval") == 0) - { - SEnviropment::Instance().m_MailInterval = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "TempDir") == 0) - { - SEnviropment::Instance().m_TempPath = AZStd::string_view{ strValue.c_str(), strValue.size() }; - } - if (azstricmp(strKey.c_str(), "MailServer") == 0) - { - SEnviropment::Instance().m_MailServer = strValue; - } - if (azstricmp(strKey.c_str(), "Caching") == 0) - { - SEnviropment::Instance().m_Caching = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintErrors") == 0) - { - SEnviropment::Instance().m_PrintErrors = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintWarnings") == 0) - { - SEnviropment::Instance().m_PrintWarnings = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintCommands") == 0) - { - SEnviropment::Instance().m_PrintCommands = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintListUpdates") == 0) - { - SEnviropment::Instance().m_PrintListUpdates = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "DedupeErrors") == 0) - { - SEnviropment::Instance().m_DedupeErrors = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "FallbackServer") == 0) - { - SEnviropment::Instance().m_FallbackServer = strValue; - } - if (azstricmp(strKey.c_str(), "FallbackTreshold") == 0) - { - SEnviropment::Instance().m_FallbackTreshold = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "DumpShaders") == 0) - { - SEnviropment::Instance().m_DumpShaders = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "MaxConnections") == 0) - { - int maxConnections = atoi(strValue.c_str()); - if (maxConnections <= 0) - { - printf("Warning: MaxConnections value is invalid. Using default value of %d\n", DEFAULT_MAX_CONNECTIONS); - } - else - { - SEnviropment::Instance().m_MaxConnections = maxConnections; - } - } - if (azstricmp(strKey.c_str(), "whitelist") == 0 || azstricmp(strKey.c_str(), "white_list") == 0) - { - std::regex ip4_address_regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))?$"); - AZStd::vector addresses; - AzFramework::StringFunc::Tokenize(strValue.c_str(), addresses, ','); - for (const auto& address : addresses) - { - if (std::regex_match(address.c_str(), ip4_address_regex)) - { - SEnviropment::Instance().m_WhitelistAddresses.push_back(address); - } - else - { - printf("Warning: invalid IP address in the whitelist field: %s", address.c_str()); - } - } - } - if (azstricmp(strKey.c_str(), "AllowElevatedPermissions") == 0) - { - int runAsRoot = atoi(strValue.c_str()); - SEnviropment::Instance().m_RunAsRoot = (runAsRoot == 1); - } - -#if defined(TOOLS_SUPPORT_JASPER) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, jasper) -#endif -#if defined(TOOLS_SUPPORT_PROVO) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, provo) -#endif -#if defined(TOOLS_SUPPORT_SALEM) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, salem) -#endif - } - - ////////////////////////////////////////////////////////////////////////// - bool ParseConfig(const char* filename) - { - FILE* file = nullptr; - azfopen(&file, filename, "rb"); - if (!file) - { - std::cout << "Config file not found" << std::endl; - return false; - } - - fseek(file, 0, SEEK_END); - int nLen = ftell(file); - fseek(file, 0, SEEK_SET); - - char* sAllText = new char [nLen + 16]; - - fread(sAllText, 1, nLen, file); - - sAllText[nLen] = '\0'; - sAllText[nLen + 1] = '\0'; - - std::string strGroup; // current group e.g. "[General]" - - char* strLast = sAllText + nLen; - char* str = sAllText; - while (str < strLast) - { - char* s = str; - while (str < strLast && *str != '\n' && *str != '\r') - { - str++; - } - *str = '\0'; - str++; - while (str < strLast && (*str == '\n' || *str == '\r')) - { - str++; - } - - - std::string strLine = s; - - // detect groups e.g. "[General]" should set strGroup="General" - { - std::string strTrimmedLine(RemoveWhiteSpaces(strLine)); - size_t size = strTrimmedLine.size(); - - if (size >= 3) - { - if (strTrimmedLine[0] == '[' && strTrimmedLine[size - 1] == ']') // currently no comments are allowed to be behind groups - { - strGroup = &strTrimmedLine[1]; - strGroup.resize(size - 2); // remove [ and ] - continue; // next line - } - } - } - - // skip comments - if (0 < strLine.find("--")) - { - // extract key - std::string::size_type posEq(strLine.find("=", 0)); - if (std::string::npos != posEq) - { - std::string stemp(strLine, 0, posEq); - std::string strKey(RemoveWhiteSpaces(stemp)); - - // if (!strKey.empty()) - { - // extract value - std::string::size_type posValueStart(strLine.find("\"", posEq + 1) + 1); - // std::string::size_type posValueEnd( strLine.find( "\"", posValueStart ) ); - std::string::size_type posValueEnd(strLine.rfind('\"')); - - std::string strValue; - - if (std::string::npos != posValueStart && std::string::npos != posValueEnd) - { - strValue = std::string(strLine, posValueStart, posValueEnd - posValueStart); - } - else - { - std::string strTmp(strLine, posEq + 1, strLine.size() - (posEq + 1)); - strValue = RemoveWhiteSpaces(strTmp); - } - OnLoadConfigurationEntry(strKey, strValue, strGroup); - } - } - } //-- - } - delete []sAllText; - fclose(file); - - return true; - } - std::string RemoveWhiteSpaces(std::string& str) - { - std::string::size_type pos1 = str.find_first_not_of(' '); - std::string::size_type pos2 = str.find_last_not_of(' '); - str = str.substr(pos1 == std::string::npos ? 0 : pos1, pos2 == std::string::npos ? str.length() - 1 : pos2 - pos1 + 1); - return str; - } - std::string AddSlash(const std::string& str) - { - if (!str.empty() && - (str[str.size() - 1] != '\\') && - (str[str.size() - 1] != '/')) - { - return str + "/"; - } - return str; - } -}; - -namespace -{ - AZ::JobManager* jobManager; - AZ::JobContext* globalJobContext; - -#if defined(AZ_PLATFORM_WINDOWS) - BOOL ControlHandler([[maybe_unused]] DWORD controlType) - { - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - return FALSE; - } -#endif -} - -void InitDefaults() -{ - SEnviropment::Instance().m_port = STD_TCP_PORT; - SEnviropment::Instance().m_MaxConnections = DEFAULT_MAX_CONNECTIONS; - SEnviropment::Instance().m_FailEMail = ""; - SEnviropment::Instance().m_MailInterval = 10; - SEnviropment::Instance().m_MailServer = "example.com"; - SEnviropment::Instance().m_Caching = true; - SEnviropment::Instance().m_PrintErrors = true; - SEnviropment::Instance().m_PrintWarnings = false; - SEnviropment::Instance().m_PrintCommands = false; - SEnviropment::Instance().m_DedupeErrors = true; - SEnviropment::Instance().m_PrintListUpdates = true; - SEnviropment::Instance().m_FallbackTreshold = 16; - SEnviropment::Instance().m_FallbackServer = ""; - SEnviropment::Instance().m_WhitelistAddresses.push_back("127.0.0.1"); - SEnviropment::Instance().m_RunAsRoot = false; - SEnviropment::Instance().InitializePlatformAttributes(); -} - -bool ReadConfigFile() -{ - char executableDir[AZ_MAX_PATH_LEN]; - if (AZ::Utils::GetExecutableDirectory(executableDir, AZ_MAX_PATH_LEN) == AZ::Utils::ExecutablePathResult::Success) - { - auto configFilename = AZ::IO::Path(executableDir).Append("config.ini"); - CConfigFile config; - config.ParseConfig(configFilename.c_str()); - return true; - } - else - { - printf("error: failed to get executable directory.\n"); - return false; - } -} - -void RunServer(bool isRunningAsRoot) -{ - if (isRunningAsRoot) - { - printf("\nWARNING: Attempting to run the CrySCompileServer as a user that has admininstrator permissions. This is a security risk and not recommended. Please run the service with a user account that does not have administrator permissions.\n\n"); - } - - if (!isRunningAsRoot || SEnviropment::Instance().m_RunAsRoot) - { - CCrySimpleHTTP HTTP; - CCrySimpleServer(); - } - else - { - printf("If you need to run CrySCompileServer with administrator permisions you can create/edit the config.ini file in the same directory as this executable and add the following line to it:\n\tAllowElevatedPermissions=1\n"); - } -} - -int main(int argc, [[maybe_unused]] char* argv[]) -{ - if (argc != 1) - { - printf("usage: run without arguments\n"); - return 0; - } - - bool isRunningAsRoot = false; - -#if defined(AZ_PLATFORM_WINDOWS) - // Check to see if we are running as root... - SID_IDENTIFIER_AUTHORITY ntAuthority = { SECURITY_NT_AUTHORITY }; - PSID administratorsGroup; - BOOL sidAllocated = AllocateAndInitializeSid( - &ntAuthority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &administratorsGroup); - - if(sidAllocated) - { - BOOL isRoot = FALSE; - if (!CheckTokenMembership( NULL, administratorsGroup, &isRoot)) - { - isRoot = FALSE; - } - FreeSid(administratorsGroup); - - isRunningAsRoot = (isRoot == TRUE); - } - -#if defined(_DEBUG) - int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - tmpFlag |= _CRTDBG_LEAK_CHECK_DF; - // tmpFlag &= ~_CRTDBG_CHECK_CRT_DF; - _CrtSetDbgFlag(tmpFlag); -#endif - AZ_Verify(SetConsoleCtrlHandler(ControlHandler, TRUE), "Unable to setup windows console control handler"); -#else - // if either the effective user id or effective group id is root, then we - // are running as root - isRunningAsRoot = (geteuid() == 0 || getegid() == 0); -#endif - - AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); - - AZ::JobManagerDesc jobManagerDescription; - - int workers = AZStd::GetMin(AZStd::thread::hardware_concurrency(), static_cast(8)); - for (int idx = 0; idx < workers; ++idx) - { - jobManagerDescription.m_workerThreads.push_back(AZ::JobManagerThreadDesc()); - } - - jobManager = aznew AZ::JobManager(jobManagerDescription); - globalJobContext = aznew AZ::JobContext(*jobManager); - AZ::JobContext::SetGlobalContext(globalJobContext); - - SEnviropment::Create(); - - InitDefaults(); - - if (ReadConfigFile()) - { - RunServer(isRunningAsRoot); - } - - SEnviropment::Destroy(); - - AZ::JobContext::SetGlobalContext(nullptr); - delete globalJobContext; - delete jobManager; - - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - - return 0; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt deleted file mode 100644 index 89d9e8d38b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt +++ /dev/null @@ -1,530 +0,0 @@ -/** @mainpage - -

TinyXML

- -TinyXML is a simple, small, C++ XML parser that can be easily -integrated into other programs. - -

What it does.

- -In brief, TinyXML parses an XML document, and builds from that a -Document Object Model (DOM) that can be read, modified, and saved. - -XML stands for "eXtensible Markup Language." It allows you to create -your own document markups. Where HTML does a very good job of marking -documents for browsers, XML allows you to define any kind of document -markup, for example a document that describes a "to do" list for an -organizer application. XML is a very structured and convenient format. -All those random file formats created to store application data can -all be replaced with XML. One parser for everything. - -The best place for the complete, correct, and quite frankly hard to -read spec is at -http://www.w3.org/TR/2004/REC-xml-20040204/. An intro to XML -(that I really like) can be found at -http://skew.org/xml/tutorial. - -There are different ways to access and interact with XML data. -TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed -into a C++ objects that can be browsed and manipulated, and then -written to disk or another output stream. You can also construct an XML document -from scratch with C++ objects and write this to disk or another output -stream. - -TinyXML is designed to be easy and fast to learn. It is two headers -and four cpp files. Simply add these to your project and off you go. -There is an example file - xmltest.cpp - to get you started. - -TinyXML is released under the ZLib license, -so you can use it in open source or commercial code. The details -of the license are at the top of every source file. - -TinyXML attempts to be a flexible parser, but with truly correct and -compliant XML output. TinyXML should compile on any reasonably C++ -compliant system. It does not rely on exceptions or RTTI. It can be -compiled with or without STL support. TinyXML fully supports -the UTF-8 encoding, and the first 64k character entities. - - -

What it doesn't do.

- -TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs -(eXtensible Stylesheet Language.) There are other parsers out there -(check out www.sourceforge.org, search for XML) that are much more fully -featured. But they are also much bigger, take longer to set up in -your project, have a higher learning curve, and often have a more -restrictive license. If you are working with browsers or have more -complete XML needs, TinyXML is not the parser for you. - -The following DTD syntax will not parse at this time in TinyXML: - -@verbatim - - ]> -@endverbatim - -because TinyXML sees this as a !DOCTYPE node with an illegally -embedded !ELEMENT node. This may be addressed in the future. - -

Tutorials.

- -For the impatient, here is a tutorial to get you going. A great way to get started, -but it is worth your time to read this (very short) manual completely. - -- @subpage tutorial0 - -

Code Status.

- -TinyXML is mature, tested code. It is very stable. If you find -bugs, please file a bug report on the sourceforge web site -(www.sourceforge.net/projects/tinyxml). We'll get them straightened -out as soon as possible. - -There are some areas of improvement; please check sourceforge if you are -interested in working on TinyXML. - -

Related Projects

- -TinyXML projects you may find useful! (Descriptions provided by the projects.) - -
    -
  • TinyXPath (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint - XPath syntax decoder, written in C++.
  • -
  • TinyXML++ (http://code.google.com/p/ticpp/). TinyXML++ is a completely new - interface to TinyXML that uses MANY of the C++ strengths. Templates, - exceptions, and much better error handling.
  • -
- -

Features

- -

Using STL

- -TinyXML can be compiled to use or not use STL. When using STL, TinyXML -uses the std::string class, and fully supports std::istream, std::ostream, -operator<<, and operator>>. Many API methods have both 'const char*' and -'const std::string&' forms. - -When STL support is compiled out, no STL files are included whatsoever. All -the string classes are implemented by TinyXML itself. API methods -all use the 'const char*' form for input. - -Use the compile time #define: - - TIXML_USE_STL - -to compile one version or the other. This can be passed by the compiler, -or set as the first line of "tinyxml.h". - -Note: If compiling the test code in Linux, setting the environment -variable TINYXML_USE_STL=YES/NO will control STL compilation. In the -Windows project file, STL and non STL targets are provided. In your project, -It's probably easiest to add the line "#define TIXML_USE_STL" as the first -line of tinyxml.h. - -

UTF-8

- -TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML -also supports "legacy mode" - the encoding used before UTF-8 support and -probably best described as "extended ascii". - -Normally, TinyXML will try to detect the correct encoding and use it. However, -by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML -can be forced to always use one encoding. - -TinyXML will assume Legacy Mode until one of the following occurs: -
    -
  1. If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf) - begin the file or data stream, TinyXML will read it as UTF-8.
  2. -
  3. If the declaration tag is read, and it has an encoding="UTF-8", then - TinyXML will read it as UTF-8.
  4. -
  5. If the declaration tag is read, and it has no encoding specified, then TinyXML will - read it as UTF-8.
  6. -
  7. If the declaration tag is read, and it has an encoding="something else", then TinyXML - will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's - not clear what that mode does exactly, but old content should keep working.
  8. -
  9. Until one of the above criteria is met, TinyXML runs in Legacy Mode.
  10. -
- -What happens if the encoding is incorrectly set or detected? TinyXML will try -to read and pass through text seen as improperly encoded. You may get some strange results or -mangled characters. You may want to force TinyXML to the correct mode. - -You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or -LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all -the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may -force it to TIXML_ENCODING_UTF8 with the same technique. - -For English users, using English XML, UTF-8 is the same as low-ASCII. You -don't need to be aware of UTF-8 or change your code in any way. You can think -of UTF-8 as a "superset" of ASCII. - -UTF-8 is not a double byte format - but it is a standard encoding of Unicode! -TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. -It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding -of unicode. This is a source of confusion. - -For "high-ascii" languages - everything not English, pretty much - TinyXML can -handle all languages, at the same time, as long as the XML is encoded -in UTF-8. That can be a little tricky, older programs and operating systems -tend to use the "default" or "traditional" code page. Many apps (and almost all -modern ones) can output UTF-8, but older or stubborn (or just broken) ones -still output text in the default code page. - -For example, Japanese systems traditionally use SHIFT-JIS encoding. -Text encoded as SHIFT-JIS can not be read by TinyXML. -A good text editor can import SHIFT-JIS and then save as UTF-8. - -The Skew.org link does a great -job covering the encoding issue. - -The test file "utf8test.xml" is an XML containing English, Spanish, Russian, -and Simplified Chinese. (Hopefully they are translated correctly). The file -"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that -if you don't have the correct fonts (Simplified Chinese or Russian) on your -system, you won't see output that matches the GIF file even if you can parse -it correctly. Also note that (at least on my Windows machine) console output -is in a Western code page, so that Print() or printf() cannot correctly display -the file. This is not a bug in TinyXML - just an OS issue. No data is lost or -destroyed by TinyXML. The console just doesn't render UTF-8. - - -

Entities

-TinyXML recognizes the pre-defined "character entities", meaning special -characters. Namely: - -@verbatim - & & - < < - > > - " " - ' ' -@endverbatim - -These are recognized when the XML document is read, and translated to there -UTF-8 equivalents. For instance, text with the XML of: - -@verbatim - Far & Away -@endverbatim - -will have the Value() of "Far & Away" when queried from the TiXmlText object, -and will be written back to the XML stream/file as an ampersand. Older versions -of TinyXML "preserved" character entities, but the newer versions will translate -them into characters. - -Additionally, any character can be specified by its Unicode code point: -The syntax " " or " " are both to the non-breaking space characher. - -

Printing

-TinyXML can print output in several different ways that all have strengths and limitations. - -- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout. - - "Pretty prints", but you don't have control over printing options. - - The output is streamed directly to the FILE object, so there is no memory overhead - in the TinyXML code. - - used by Print() and SaveFile() - -- operator<<. Output to a c++ stream. - - Integrates with standart C++ iostreams. - - Outputs in "network printing" mode without line breaks. Good for network transmission - and moving XML between C++ objects, but hard for a human to read. - -- TiXmlPrinter. Output to a std::string or memory buffer. - - API is less concise - - Future printing options will be put here. - - Printing may change slightly in future versions as it is refined and expanded. - -

Streams

-With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well -as C (FILE*) streams. There are some differences that you may need to be aware of. - -C style output: - - based on FILE* - - the Print() and SaveFile() methods - - Generates formatted output, with plenty of white space, intended to be as - human-readable as possible. They are very fast, and tolerant of ill formed - XML documents. For example, an XML document that contains 2 root elements - and 2 declarations, will still print. - -C style input: - - based on FILE* - - the Parse() and LoadFile() methods - - A fast, tolerant read. Use whenever you don't need the C++ streams. - -C++ style output: - - based on std::ostream - - operator<< - - Generates condensed output, intended for network transmission rather than - readability. Depending on your system's implementation of the ostream class, - these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML: - a document should contain the correct one root element. Additional root level - elements will not be streamed out. - -C++ style input: - - based on std::istream - - operator>> - - Reads XML from a stream, making it useful for network transmission. The tricky - part is knowing when the XML document is complete, since there will almost - certainly be other data in the stream. TinyXML will assume the XML data is - complete after it reads the root element. Put another way, documents that - are ill-constructed with more than one root element will not read correctly. - Also note that operator>> is somewhat slower than Parse, due to both - implementation of the STL and limitations of TinyXML. - -

White space

-The world simply does not agree on whether white space should be kept, or condensed. -For example, pretend the '_' is a space, and look at "Hello____world". HTML, and -at least some XML parsers, will interpret this as "Hello_world". They condense white -space. Some XML parsers do not, and will leave it as "Hello____world". (Remember -to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become -Hello___world. - -It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the -first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior. -The default is to condense white space. - -If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool ) -before making any calls to Parse XML data, and I don't recommend changing it after -it has been set. - - -

Handles

- -Where browsing an XML document in a robust way, it is important to check -for null returns from method calls. An error safe implementation can -generate a lot of code like: - -@verbatim -TiXmlElement* root = document.FirstChildElement( "Document" ); -if ( root ) -{ - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. -@endverbatim - -Handles have been introduced to clean this up. Using the TiXmlHandle class, -the previous code reduces to: - -@verbatim -TiXmlHandle docHandle( &document ); -TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); -if ( child2 ) -{ - // do something useful -@endverbatim - -Which is much easier to deal with. See TiXmlHandle for more information. - - -

Row and Column tracking

-Being able to track nodes and attributes back to their origin location -in source files can be very important for some applications. Additionally, -knowing where parsing errors occured in the original source can be very -time saving. - -TinyXML can tracks the row and column origin of all nodes and attributes -in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return -the origin of the node in the source text. The correct tabs can be -configured in TiXmlDocument::SetTabSize(). - - -

Using and Installing

- -To Compile and Run xmltest: - -A Linux Makefile and a Windows Visual C++ .dsw file is provided. -Simply compile and run. It will write the file demotest.xml to your -disk and generate output on the screen. It also tests walking the -DOM by printing out the number of nodes found using different -techniques. - -The Linux makefile is very generic and runs on many systems - it -is currently tested on mingw and -MacOSX. You do not need to run 'make depend'. The dependecies have been -hard coded. - -

Windows project file for VC6

-
    -
  • tinyxml: tinyxml library, non-STL
  • -
  • tinyxmlSTL: tinyxml library, STL
  • -
  • tinyXmlTest: test app, non-STL
  • -
  • tinyXmlTestSTL: test app, STL
  • -
- -

Makefile

-At the top of the makefile you can set: - -PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in -the makefile. - -In the tinyxml directory, type "make clean" then "make". The executable -file 'xmltest' will be created. - - - -

To Use in an Application:

- -Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your -project or make file. That's it! It should compile on any reasonably -compliant C++ system. You do not need to enable exceptions or -RTTI for TinyXML. - - -

How TinyXML works.

- -An example is probably the best way to go. Take: -@verbatim - - - - Go to the Toy store! - Do bills - -@endverbatim - -Its not much of a To Do list, but it will do. To read this file -(say "demo.xml") you would create a document, and parse it in: -@verbatim - TiXmlDocument doc( "demo.xml" ); - doc.LoadFile(); -@endverbatim - -And its ready to go. Now lets look at some lines and how they -relate to the DOM. - -@verbatim - -@endverbatim - - The first line is a declaration, and gets turned into the - TiXmlDeclaration class. It will be the first child of the - document node. - - This is the only directive/special tag parsed by TinyXML. - Generally directive tags are stored in TiXmlUnknown so the - commands wont be lost when it is saved back to disk. - -@verbatim - -@endverbatim - - A comment. Will become a TiXmlComment object. - -@verbatim - -@endverbatim - - The "ToDo" tag defines a TiXmlElement object. This one does not have - any attributes, but does contain 2 other elements. - -@verbatim - -@endverbatim - - Creates another TiXmlElement which is a child of the "ToDo" element. - This element has 1 attribute, with the name "priority" and the value - "1". - -@verbatim -Go to the -@endverbatim - - A TiXmlText. This is a leaf node and cannot contain other nodes. - It is a child of the "Item" TiXmlElement. - -@verbatim - -@endverbatim - - - Another TiXmlElement, this one a child of the "Item" element. - -Etc. - -Looking at the entire object tree, you end up with: -@verbatim -TiXmlDocument "demo.xml" - TiXmlDeclaration "version='1.0'" "standalone=no" - TiXmlComment " Our to do list data" - TiXmlElement "ToDo" - TiXmlElement "Item" Attribtutes: priority = 1 - TiXmlText "Go to the " - TiXmlElement "bold" - TiXmlText "Toy store!" - TiXmlElement "Item" Attributes: priority=2 - TiXmlText "Do bills" -@endverbatim - -

Documentation

- -The documentation is build with Doxygen, using the 'dox' -configuration file. - -

License

- -TinyXML is released under the zlib license: - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - -

References

- -The World Wide Web Consortium is the definitive standard body for -XML, and their web pages contain huge amounts of information. - -The definitive spec: -http://www.w3.org/TR/2004/REC-xml-20040204/ - -I also recommend "XML Pocket Reference" by Robert Eckstein and published by -OReilly...the book that got the whole thing started. - -

Contributors, Contacts, and a Brief History

- -Thanks very much to everyone who sends suggestions, bugs, ideas, and -encouragement. It all helps, and makes this project fun. A special thanks -to the contributors on the web pages that keep it lively. - -So many people have sent in bugs and ideas, that rather than list here -we try to give credit due in the "changes.txt" file. - -TinyXML was originally written by Lee Thomason. (Often the "I" still -in the documentation.) Lee reviews changes and releases new versions, -with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community. - -We appreciate your suggestions, and would love to know if you -use TinyXML. Hopefully you will enjoy it and find it useful. -Please post questions, comments, file bugs, or contact us at: - -www.sourceforge.net/projects/tinyxml - -Lee Thomason, Yves Berquin, Andrew Ellerton -*/ diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp deleted file mode 100644 index b0e117d674..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. - */ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h deleted file mode 100644 index ab0cc81547..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h +++ /dev/null @@ -1,309 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates. - -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - // = operator - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - // = operator - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp deleted file mode 100644 index 0915c669b3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp +++ /dev/null @@ -1,1889 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - // Not using fopen_s() as it's not available in Mac or Linux - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::DOCUMENT ) - { - delete node; - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( replaceThis->parent != this ) - return 0; - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -void TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return &node->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const char* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s ); - } - else { - *i = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const std::string* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s->c_str() ); - } - else { - *i = 0; - } - } - return s; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const char* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s ); - } - else { - *d = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const std::string* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s->c_str() ); - } - else { - *d = 0; - } - } - return s; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - char buf[64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); - #else - sprintf( buf, "%d", val ); - #endif - SetAttribute( name, buf ); -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - std::ostringstream oss; - oss << val; - SetAttribute( name, oss.str() ); -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - char buf[256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); - #else - sprintf( buf, "%f", val ); - #endif - SetAttribute( name, buf ); -} - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING _name( cname ); - TIXML_STRING _value( cvalue ); - #else - const char* _name = cname; - const char* _value = cvalue; - #endif - - TiXmlAttribute* node = attributeSet.Find( _name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) -{ - TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - // See STL_STRING_BUG below. - //StringToBuffer buf( value ); - - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - // See STL_STRING_BUG below. -// StringToBuffer buf( value ); -// -// if ( buf.buffer && SaveFile( buf.buffer ) ) -// return true; -// -// return false; - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - // There was a really terrifying little bug here. The code: - // value = filename - // in the STL case, cause the assignment method of the std::string to - // be called. What is strange, is that the std::string had the same - // address as it's c_str() method, and so bad things happen. Looks - // like a bug in the Microsoft STL implementation. - // Add an extra string to avoid the crash. - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // If we have a file, assume it is all one big XML file, and read it in. - // The document parser may decide the document ends sooner than the entire file, however. - TIXML_STRING data; - data.reserve( length ); - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - const char* lastPos = buf; - const char* p = buf; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - if ( *p == 0xa ) { - // Newline character. No special rules for this. Append all the characters - // since the last string, and include the newline. - data.append( lastPos, (p-lastPos+1) ); // append, include the newline - ++p; // move past the newline - lastPos = p; // and point to the new buffer (may be 0) - assert( p <= (buf+length) ); - } - else if ( *p == 0xd ) { - // Carriage return. Append what we have so far, then - // handle moving forward in the buffer. - if ( (p-lastPos) > 0 ) { - data.append( lastPos, p-lastPos ); // do not add the CR - } - data += (char)0xa; // a proper newline - - if ( *(p+1) == 0xa ) { - // Carriage return - new line sequence - p += 2; - lastPos = p; - assert( p <= (buf+length) ); - } - else { - // it was followed by something else...that is presumably characters again. - ++p; - lastPos = p; - assert( p <= (buf+length) ); - } - } - else { - ++p; - } - } - // Handle any left over characters. - if ( p-lastPos ) { - data.append( lastPos, p-lastPos ); - } - delete [] buf; - buf = 0; - - Parse( data.c_str(), 0, encoding ); - - if ( Error() ) - return false; - else - return true; -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); - #else - sprintf (buf, "%lf", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} -*/ -#endif - - -const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} -*/ - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h deleted file mode 100644 index c230c02afb..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h +++ /dev/null @@ -1,1785 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SNSCANF _snscanf_s - #define TIXML_SSCANF sscanf_s - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SNSCANF snscanf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 5; -const int TIXML_PATCH_VERSION = 3; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simple called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_OUT_OF_MEMORY, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - DOCUMENT, - ELEMENT, - COMMENT, - UNKNOWN, - TEXT, - DECLARATION, - TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - const TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* Find( const char* _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - #ifdef TIXML_USE_STL - const TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* Find( const std::string& _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - - #endif - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - /* - This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" - but template specialization is hard to get working cross-compiler. Leaving the bug for now. - - // The above will fail for std::string because the space character is used as a seperator. - // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string - template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - */ - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && LoadFile( f.buffer, encoding )); - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && SaveFile( f.buffer )); - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -#include - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p ) - p += strlen( endTag ); - return p; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - TiXmlDocument* doc = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - -// int tabsize = 4; -// if ( document ) -// tabsize = document->TabSize(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i - #include -using namespace std; -#else - #include -#endif - -#if defined(WIN32) && defined(TUNE) - #include -_CrtMemState startMemState; -_CrtMemState endMemState; -#endif - -#include "tinyxml.h" - -static int gPass = 0; -static int gFail = 0; - - -bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false) -{ - bool pass = !strcmp(expected, found); - if (pass) - { - printf ("[pass]"); - } - else - { - printf ("[fail]"); - } - - if (noEcho) - { - printf (" %s\n", testString); - } - else - { - printf (" %s [%s][%s]\n", testString, expected, found); - } - - if (pass) - { - ++gPass; - } - else - { - ++gFail; - } - return pass; -} - - -bool XmlTest(const char* testString, int expected, int found, bool noEcho = false) -{ - bool pass = (expected == found); - if (pass) - { - printf ("[pass]"); - } - else - { - printf ("[fail]"); - } - - if (noEcho) - { - printf (" %s\n", testString); - } - else - { - printf (" %s [%d][%d]\n", testString, expected, found); - } - - if (pass) - { - ++gPass; - } - else - { - ++gFail; - } - return pass; -} - - -// -// This file demonstrates some basic functionality of TinyXml. -// Note that the example is very contrived. It presumes you know -// what is in the XML file. But it does test the basic operations, -// and show how to add and remove nodes. -// - -int main() -{ - // - // We start with the 'demoStart' todo list. Process it. And - // should hopefully end up with the todo list as illustrated. - // - const char* demoStart = - "\n" - "" - "\n" - "\n" - " Go to the Toy store!" - " Do bills " - " Look for Evil Dinosaurs! " - ""; - - { - #ifdef TIXML_USE_STL - /* What the todo list should look like after processing. - In stream (no formatting) representation. */ - const char* demoEnd = - "" - "" - "" - "" - "Go to the" - "Toy store!" - "" - "" - "Talk to:" - "" - "" - "" - "" - "" - "" - "Do bills" - "" - ""; - #endif - - // The example parses from the character string (above): - #if defined(WIN32) && defined(TUNE) - _CrtMemCheckpoint(&startMemState); - #endif - - { - // Write to a file and read it back, to check file I/O. - - TiXmlDocument doc("demotest.xml"); - doc.Parse(demoStart); - - if (doc.Error()) - { - printf("Error in %s: %s\n", doc.Value(), doc.ErrorDesc()); - exit(1); - } - doc.SaveFile(); - } - - TiXmlDocument doc("demotest.xml"); - bool loadOkay = doc.LoadFile(); - - if (!loadOkay) - { - printf("Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc()); - exit(1); - } - - printf("** Demo doc read from disk: ** \n\n"); - printf("** Printing via doc.Print **\n"); - doc.Print(stdout); - - { - printf("** Printing via TiXmlPrinter **\n"); - TiXmlPrinter printer; - doc.Accept(&printer); - fprintf(stdout, "%s", printer.CStr()); - } - #ifdef TIXML_USE_STL - { - printf("** Printing via operator<< **\n"); - std::cout << doc; - } - #endif - TiXmlNode* node = 0; - TiXmlElement* todoElement = 0; - TiXmlElement* itemElement = 0; - - - // -------------------------------------------------------- - // An example of changing existing attributes, and removing - // an element from the document. - // -------------------------------------------------------- - - // Get the "ToDo" element. - // It is a child of the document, and can be selected by name. - node = doc.FirstChild("ToDo"); - assert(node); - todoElement = node->ToElement(); - assert(todoElement); - - // Going to the toy store is now our second priority... - // So set the "priority" attribute of the first item in the list. - node = todoElement->FirstChildElement(); // This skips the "PDA" comment. - assert(node); - itemElement = node->ToElement(); - assert(itemElement); - itemElement->SetAttribute("priority", 2); - - // Change the distance to "doing bills" from - // "none" to "here". It's the next sibling element. - itemElement = itemElement->NextSiblingElement(); - assert(itemElement); - itemElement->SetAttribute("distance", "here"); - - // Remove the "Look for Evil Dinosaurs!" item. - // It is 1 more sibling away. We ask the parent to remove - // a particular child. - itemElement = itemElement->NextSiblingElement(); - todoElement->RemoveChild(itemElement); - - itemElement = 0; - - // -------------------------------------------------------- - // What follows is an example of created elements and text - // nodes and adding them to the document. - // -------------------------------------------------------- - - // Add some meetings. - TiXmlElement item("Item"); - item.SetAttribute("priority", "1"); - item.SetAttribute("distance", "far"); - - TiXmlText text("Talk to:"); - - TiXmlElement meeting1("Meeting"); - meeting1.SetAttribute("where", "School"); - - TiXmlElement meeting2("Meeting"); - meeting2.SetAttribute("where", "Lunch"); - - TiXmlElement attendee1("Attendee"); - attendee1.SetAttribute("name", "Marple"); - attendee1.SetAttribute("position", "teacher"); - - TiXmlElement attendee2("Attendee"); - attendee2.SetAttribute("name", "Voel"); - attendee2.SetAttribute("position", "counselor"); - - // Assemble the nodes we've created: - meeting1.InsertEndChild(attendee1); - meeting1.InsertEndChild(attendee2); - - item.InsertEndChild(text); - item.InsertEndChild(meeting1); - item.InsertEndChild(meeting2); - - // And add the node to the existing list after the first child. - node = todoElement->FirstChild("Item"); - assert(node); - itemElement = node->ToElement(); - assert(itemElement); - - todoElement->InsertAfterChild(itemElement, item); - - printf("\n** Demo doc processed: ** \n\n"); - doc.Print(stdout); - - - #ifdef TIXML_USE_STL - printf("** Demo doc processed to stream: ** \n\n"); - cout << doc << endl << endl; - #endif - - // -------------------------------------------------------- - // Different tests...do we have what we expect? - // -------------------------------------------------------- - - int count = 0; - TiXmlElement* element; - - ////////////////////////////////////////////////////// - - #ifdef TIXML_USE_STL - cout << "** Basic structure. **\n"; - ostringstream outputStream(ostringstream::out); - outputStream << doc; - XmlTest("Output stream correct.", string(demoEnd).c_str(), - outputStream.str().c_str(), true); - #endif - - node = doc.RootElement(); - assert(node); - XmlTest("Root element exists.", true, (node != 0 && node->ToElement())); - XmlTest ("Root element value is 'ToDo'.", "ToDo", node->Value()); - - node = node->FirstChild(); - XmlTest("First child exists & is a comment.", true, (node != 0 && node->ToComment())); - node = node->NextSibling(); - XmlTest("Sibling element exists & is an element.", true, (node != 0 && node->ToElement())); - XmlTest ("Value is 'Item'.", "Item", node->Value()); - - node = node->FirstChild(); - XmlTest ("First child exists.", true, (node != 0 && node->ToText())); - XmlTest ("Value is 'Go to the'.", "Go to the", node->Value()); - - - ////////////////////////////////////////////////////// - printf ("\n** Iterators. **\n"); - - // Walk all the top level nodes of the document. - count = 0; - for (node = doc.FirstChild(); - node; - node = node->NextSibling()) - { - count++; - } - XmlTest("Top level nodes, using First / Next.", 3, count); - - count = 0; - for (node = doc.LastChild(); - node; - node = node->PreviousSibling()) - { - count++; - } - XmlTest("Top level nodes, using Last / Previous.", 3, count); - - // Walk all the top level nodes of the document, - // using a different syntax. - count = 0; - for (node = doc.IterateChildren(0); - node; - node = doc.IterateChildren(node)) - { - count++; - } - XmlTest("Top level nodes, using IterateChildren.", 3, count); - - // Walk all the elements in a node. - count = 0; - for (element = todoElement->FirstChildElement(); - element; - element = element->NextSiblingElement()) - { - count++; - } - XmlTest("Children of the 'ToDo' element, using First / Next.", - 3, count); - - // Walk all the elements in a node by value. - count = 0; - for (node = todoElement->FirstChild("Item"); - node; - node = node->NextSibling("Item")) - { - count++; - } - XmlTest("'Item' children of the 'ToDo' element, using First/Next.", 3, count); - - count = 0; - for (node = todoElement->LastChild("Item"); - node; - node = node->PreviousSibling("Item")) - { - count++; - } - XmlTest("'Item' children of the 'ToDo' element, using Last/Previous.", 3, count); - - #ifdef TIXML_USE_STL - { - cout << "\n** Parsing. **\n"; - istringstream parse0(""); - TiXmlElement element0("default"); - parse0 >> element0; - - XmlTest ("Element parsed, value is 'Element0'.", "Element0", element0.Value()); - XmlTest ("Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute("attribute0")); - XmlTest ("Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute("attribute1")); - XmlTest ("Read attribute with entity value '>'.", ">", element0.Attribute("attribute2")); - } - #endif - - { - const char* error = "\n" - "\n" - " \n" - ""; - - TiXmlDocument docTest; - docTest.Parse(error); - XmlTest("Error row", docTest.ErrorRow(), 3); - XmlTest("Error column", docTest.ErrorCol(), 17); - //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); - } - - #ifdef TIXML_USE_STL - { - ////////////////////////////////////////////////////// - cout << "\n** Streaming. **\n"; - - // Round trip check: stream in, then stream back out to verify. The stream - // out has already been checked, above. We use the output - - istringstream inputStringStream(outputStream.str()); - TiXmlDocument document0; - - inputStringStream >> document0; - - ostringstream outputStream0(ostringstream::out); - outputStream0 << document0; - - XmlTest("Stream round trip correct.", string(demoEnd).c_str(), - outputStream0.str().c_str(), true); - - std::string str; - str << document0; - - XmlTest("String printing correct.", string(demoEnd).c_str(), - str.c_str(), true); - } - #endif - } - - { - const char* str = ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlElement* ele = doc.FirstChildElement(); - - int iVal, result; - double dVal; - - result = ele->QueryDoubleAttribute("attr0", &dVal); - XmlTest("Query attribute: int as double", result, TIXML_SUCCESS); - XmlTest("Query attribute: int as double", (int)dVal, 1); - result = ele->QueryDoubleAttribute("attr1", &dVal); - XmlTest("Query attribute: double as double", (int)dVal, 2); - result = ele->QueryIntAttribute("attr1", &iVal); - XmlTest("Query attribute: double as int", result, TIXML_SUCCESS); - XmlTest("Query attribute: double as int", iVal, 2); - result = ele->QueryIntAttribute("attr2", &iVal); - XmlTest("Query attribute: not a number", result, TIXML_WRONG_TYPE); - result = ele->QueryIntAttribute("bar", &iVal); - XmlTest("Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE); - } - - { - const char* str = "\t\t\n" - ""; - - TiXmlDocument doc; - doc.SetTabSize(8); - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle roomHandle = docHandle.FirstChildElement("room"); - - assert(docHandle.Node()); - assert(roomHandle.Element()); - - TiXmlElement* room = roomHandle.Element(); - assert(room); - TiXmlAttribute* doors = room->FirstAttribute(); - assert(doors); - - XmlTest("Location tracking: Tab 8: room row", room->Row(), 1); - XmlTest("Location tracking: Tab 8: room col", room->Column(), 49); - XmlTest("Location tracking: Tab 8: doors row", doors->Row(), 1); - XmlTest("Location tracking: Tab 8: doors col", doors->Column(), 55); - } - - { - const char* str = "\t\t\n" - " \n" - " A great door!\n" - "\t" - ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle roomHandle = docHandle.FirstChildElement("room"); - TiXmlHandle commentHandle = docHandle.FirstChildElement("room").FirstChild(); - TiXmlHandle textHandle = docHandle.FirstChildElement("room").ChildElement("door", 0).FirstChild(); - TiXmlHandle door0Handle = docHandle.FirstChildElement("room").ChildElement(0); - TiXmlHandle door1Handle = docHandle.FirstChildElement("room").ChildElement(1); - - assert(docHandle.Node()); - assert(roomHandle.Element()); - assert(commentHandle.Node()); - assert(textHandle.Text()); - assert(door0Handle.Element()); - assert(door1Handle.Element()); - - TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); - assert(declaration); - TiXmlElement* room = roomHandle.Element(); - assert(room); - TiXmlAttribute* doors = room->FirstAttribute(); - assert(doors); - TiXmlText* text = textHandle.Text(); - TiXmlComment* comment = commentHandle.Node()->ToComment(); - assert(comment); - TiXmlElement* door0 = door0Handle.Element(); - TiXmlElement* door1 = door1Handle.Element(); - - XmlTest("Location tracking: Declaration row", declaration->Row(), 1); - XmlTest("Location tracking: Declaration col", declaration->Column(), 5); - XmlTest("Location tracking: room row", room->Row(), 1); - XmlTest("Location tracking: room col", room->Column(), 45); - XmlTest("Location tracking: doors row", doors->Row(), 1); - XmlTest("Location tracking: doors col", doors->Column(), 51); - XmlTest("Location tracking: Comment row", comment->Row(), 2); - XmlTest("Location tracking: Comment col", comment->Column(), 3); - XmlTest("Location tracking: text row", text->Row(), 3); - XmlTest("Location tracking: text col", text->Column(), 24); - XmlTest("Location tracking: door0 row", door0->Row(), 3); - XmlTest("Location tracking: door0 col", door0->Column(), 5); - XmlTest("Location tracking: door1 row", door1->Row(), 4); - XmlTest("Location tracking: door1 col", door1->Column(), 5); - } - - - // -------------------------------------------------------- - // UTF-8 testing. It is important to test: - // 1. Making sure name, value, and text read correctly - // 2. Row, Col functionality - // 3. Correct output - // -------------------------------------------------------- - printf ("\n** UTF-8 **\n"); - { - TiXmlDocument doc("utf8test.xml"); - doc.LoadFile(); - if (doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE) - { - printf("WARNING: File 'utf8test.xml' not found.\n" - "(Are you running the test from the wrong directory?)\n" - "Could not test UTF-8 functionality.\n"); - } - else - { - TiXmlHandle docH(&doc); - // Get the attribute "value" from the "Russian" element and check it. - TiXmlElement* element = docH.FirstChildElement("document").FirstChildElement("Russian").Element(); - const unsigned char correctValue[] = { - 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, - 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 - }; - - XmlTest("UTF-8: Russian value.", (const char*)correctValue, element->Attribute("value"), true); - XmlTest("UTF-8: Russian value row.", 4, element->Row()); - XmlTest("UTF-8: Russian value column.", 5, element->Column()); - - const unsigned char russianElementName[] = { - 0xd0U, 0xa0U, 0xd1U, 0x83U, - 0xd1U, 0x81U, 0xd1U, 0x81U, - 0xd0U, 0xbaU, 0xd0U, 0xb8U, - 0xd0U, 0xb9U, 0 - }; - const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; - - TiXmlText* text = docH.FirstChildElement("document").FirstChildElement((const char*) russianElementName).Child(0).Text(); - XmlTest("UTF-8: Browsing russian element name.", - russianText, - text->Value(), - true); - XmlTest("UTF-8: Russian element name row.", 7, text->Row()); - XmlTest("UTF-8: Russian element name column.", 47, text->Column()); - - TiXmlDeclaration* dec = docH.Child(0).Node()->ToDeclaration(); - XmlTest("UTF-8: Declaration column.", 1, dec->Column()); - XmlTest("UTF-8: Document column.", 1, doc.Column()); - - // Now try for a round trip. - doc.SaveFile("utf8testout.xml"); - - // Check the round trip. - char savedBuf[256]; - char verifyBuf[256]; - int okay = 1; - - FILE* saved = fopen("utf8testout.xml", "r"); - FILE* verify = fopen("utf8testverify.xml", "r"); - if (saved && verify) - { - while (fgets(verifyBuf, 256, verify)) - { - fgets(savedBuf, 256, saved); - if (strcmp(verifyBuf, savedBuf)) - { - okay = 0; - break; - } - } - } - if(saved) - { - fclose(saved); - } - if(verify) - { - fclose(verify); - } - XmlTest("UTF-8: Verified multi-language round trip.", 1, okay); - - // On most Western machines, this is an element that contains - // the word "resume" with the correct accents, in a latin encoding. - // It will be something else completely on non-wester machines, - // which is why TinyXml is switching to UTF-8. - const char latin[] = "r\x82sum\x82"; - - TiXmlDocument latinDoc; - latinDoc.Parse(latin, 0, TIXML_ENCODING_LEGACY); - - text = latinDoc.FirstChildElement()->FirstChild()->ToText(); - XmlTest("Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value()); - } - } - - ////////////////////// - // Copy and assignment - ////////////////////// - printf ("\n** Copy and Assignment **\n"); - { - TiXmlElement element("foo"); - element.Parse("", 0, TIXML_ENCODING_UNKNOWN); - - TiXmlElement elementCopy(element); - TiXmlElement elementAssign("foo"); - elementAssign.Parse("", 0, TIXML_ENCODING_UNKNOWN); - elementAssign = element; - - XmlTest("Copy/Assign: element copy #1.", "element", elementCopy.Value()); - XmlTest("Copy/Assign: element copy #2.", "value", elementCopy.Attribute("name")); - XmlTest("Copy/Assign: element assign #1.", "element", elementAssign.Value()); - XmlTest("Copy/Assign: element assign #2.", "value", elementAssign.Attribute("name")); - XmlTest("Copy/Assign: element assign #3.", true, (0 == elementAssign.Attribute("foo"))); - - TiXmlComment comment; - comment.Parse("", 0, TIXML_ENCODING_UNKNOWN); - TiXmlComment commentCopy(comment); - TiXmlComment commentAssign; - commentAssign = commentCopy; - XmlTest("Copy/Assign: comment copy.", "comment", commentCopy.Value()); - XmlTest("Copy/Assign: comment assign.", "comment", commentAssign.Value()); - - TiXmlUnknown unknown; - unknown.Parse("<[unknown]>", 0, TIXML_ENCODING_UNKNOWN); - TiXmlUnknown unknownCopy(unknown); - TiXmlUnknown unknownAssign; - unknownAssign.Parse("incorrect", 0, TIXML_ENCODING_UNKNOWN); - unknownAssign = unknownCopy; - XmlTest("Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value()); - XmlTest("Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value()); - - TiXmlText text("TextNode"); - TiXmlText textCopy(text); - TiXmlText textAssign("incorrect"); - textAssign = text; - XmlTest("Copy/Assign: text copy.", "TextNode", textCopy.Value()); - XmlTest("Copy/Assign: text assign.", "TextNode", textAssign.Value()); - - TiXmlDeclaration dec; - dec.Parse("", 0, TIXML_ENCODING_UNKNOWN); - TiXmlDeclaration decCopy(dec); - TiXmlDeclaration decAssign; - decAssign = dec; - - XmlTest("Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding()); - XmlTest("Copy/Assign: text assign.", "UTF-8", decAssign.Encoding()); - - TiXmlDocument doc; - elementCopy.InsertEndChild(textCopy); - doc.InsertEndChild(decAssign); - doc.InsertEndChild(elementCopy); - doc.InsertEndChild(unknownAssign); - - TiXmlDocument docCopy(doc); - TiXmlDocument docAssign; - docAssign = docCopy; - - #ifdef TIXML_USE_STL - std::string original, copy, assign; - original << doc; - copy << docCopy; - assign << docAssign; - XmlTest("Copy/Assign: document copy.", original.c_str(), copy.c_str(), true); - XmlTest("Copy/Assign: document assign.", original.c_str(), assign.c_str(), true); - - #endif - } - - ////////////////////////////////////////////////////// -#ifdef TIXML_USE_STL - printf ("\n** Parsing, no Condense Whitespace **\n"); - TiXmlBase::SetCondenseWhiteSpace(false); - { - istringstream parse1("This is \ntext"); - TiXmlElement text1("text"); - parse1 >> text1; - - XmlTest ("Condense white space OFF.", "This is \ntext", - text1.FirstChild()->Value(), - true); - } - TiXmlBase::SetCondenseWhiteSpace(true); -#endif - - ////////////////////////////////////////////////////// - // GetText(); - { - const char* str = "This is text"; - TiXmlDocument doc; - doc.Parse(str); - const TiXmlElement* element = doc.RootElement(); - - XmlTest("GetText() normal use.", "This is text", element->GetText()); - - str = "This is text"; - doc.Clear(); - doc.Parse(str); - element = doc.RootElement(); - - XmlTest("GetText() contained element.", element->GetText() == 0, true); - - str = "This is text"; - doc.Clear(); - TiXmlBase::SetCondenseWhiteSpace(false); - doc.Parse(str); - TiXmlBase::SetCondenseWhiteSpace(true); - element = doc.RootElement(); - - XmlTest("GetText() partial.", "This is ", element->GetText()); - } - - - ////////////////////////////////////////////////////// - // CDATA - { - const char* str = "" - " the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse(str); - doc.Print(); - - XmlTest("CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - - #ifdef TIXML_USE_STL - //cout << doc << '\n'; - - doc.Clear(); - - istringstream parse0(str); - parse0 >> doc; - //cout << doc << '\n'; - - XmlTest("CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest("CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - } - { - // [ 1482728 ] Wrong wide char parsing - char buf[256]; - buf[255] = 0; - for (int i = 0; i < 255; ++i) - { - buf[i] = (char)((i >= 32) ? i : 32); - } - TIXML_STRING str(""; - - TiXmlDocument doc; - doc.Parse(str.c_str()); - - TiXmlPrinter printer; - printer.SetStreamPrinting(); - doc.Accept(&printer); - - XmlTest("CDATA with all bytes #1.", str.c_str(), printer.CStr(), true); - - #ifdef TIXML_USE_STL - doc.Clear(); - istringstream iss(printer.Str()); - iss >> doc; - std::string out; - out << doc; - XmlTest("CDATA with all bytes #2.", out.c_str(), printer.CStr(), true); - #endif - } - { - // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags - // CDATA streaming had a couple of bugs, that this tests for. - const char* str = "" - "I am > the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse(str); - doc.Print(); - - XmlTest("CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - - #ifdef TIXML_USE_STL - - doc.Clear(); - - istringstream parse0(str); - parse0 >> doc; - - XmlTest("CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest("CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - } - ////////////////////////////////////////////////////// - // Visit() - - - - ////////////////////////////////////////////////////// - printf("\n** Fuzzing... **\n"); - - const int FUZZ_ITERATION = 300; - - // The only goal is not to crash on bad input. - int len = (int) strlen(demoStart); - for (int i = 0; i < FUZZ_ITERATION; ++i) - { - char* demoCopy = new char[ len + 1 ]; - strcpy(demoCopy, demoStart); - - demoCopy[ i % len ] = (char)((i + 1) * 3); - demoCopy[ (i * 7) % len ] = '>'; - demoCopy[ (i * 11) % len ] = '<'; - - TiXmlDocument xml; - xml.Parse(demoCopy); - - delete [] demoCopy; - } - printf("** Fuzzing Complete. **\n"); - - ////////////////////////////////////////////////////// - printf ("\n** Bug regression tests **\n"); - - // InsertBeforeChild and InsertAfterChild causes crash. - { - TiXmlElement parent("Parent"); - TiXmlElement childText0("childText0"); - TiXmlElement childText1("childText1"); - TiXmlNode* childNode0 = parent.InsertEndChild(childText0); - TiXmlNode* childNode1 = parent.InsertBeforeChild(childNode0, childText1); - - XmlTest("Test InsertBeforeChild on empty node.", (childNode1 == parent.FirstChild()), true); - } - - { - // InsertBeforeChild and InsertAfterChild causes crash. - TiXmlElement parent("Parent"); - TiXmlElement childText0("childText0"); - TiXmlElement childText1("childText1"); - TiXmlNode* childNode0 = parent.InsertEndChild(childText0); - TiXmlNode* childNode1 = parent.InsertAfterChild(childNode0, childText1); - - XmlTest("Test InsertAfterChild on empty node. ", (childNode1 == parent.LastChild()), true); - } - - // Reports of missing constructors, irregular string problems. - { - // Missing constructor implementation. No test -- just compiles. - TiXmlText text("Missing"); - - #ifdef TIXML_USE_STL - // Missing implementation: - TiXmlDocument doc; - string name = "missing"; - doc.LoadFile(name); - - TiXmlText textSTL(name); - #else - // verifying some basic string functions: - TiXmlString a; - TiXmlString b("Hello"); - TiXmlString c("ooga"); - - c = " World!"; - a = b; - a += c; - a = a; - - XmlTest("Basic TiXmlString test. ", "Hello World!", a.c_str()); - #endif - } - - // Long filenames crashing STL version - { - TiXmlDocument doc("midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml"); - bool loadOkay = doc.LoadFile(); - loadOkay = true; // get rid of compiler warning. - // Won't pass on non-dev systems. Just a "no crash" check. - //XmlTest( "Long filename. ", true, loadOkay ); - } - - { - // Entities not being written correctly. - // From Lynn Allen - - const char* passages = - "" - "" - " " - ""; - - TiXmlDocument doc("passages.xml"); - doc.Parse(passages); - TiXmlElement* psg = doc.RootElement()->FirstChildElement(); - const char* context = psg->Attribute("context"); - const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; - - XmlTest("Entity transformation: read. ", expected, context, true); - - FILE* textfile = fopen("textfile.txt", "w"); - if (textfile) - { - psg->Print(textfile, 0); - fclose(textfile); - } - textfile = fopen("textfile.txt", "r"); - assert(textfile); - if (textfile) - { - char buf[ 1024 ]; - fgets(buf, 1024, textfile); - XmlTest("Entity transformation: write. ", - "", - buf, - true); - } - fclose(textfile); - } - - { - FILE* textfile = fopen("test5.xml", "w"); - if (textfile) - { - fputs("", textfile); - fclose(textfile); - - TiXmlDocument doc; - doc.LoadFile("test5.xml"); - XmlTest("dot in element attributes and names", doc.Error(), 0); - } - } - - { - FILE* textfile = fopen("test6.xml", "w"); - if (textfile) - { - fputs("1.1 Start easy ignore fin thickness ", textfile); - fclose(textfile); - - TiXmlDocument doc; - bool result = doc.LoadFile("test6.xml"); - XmlTest("Entity with one digit.", result, true); - - TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); - XmlTest("Entity with one digit.", - text->Value(), "1.1 Start easy ignore fin thickness\n"); - } - } - - { - // DOCTYPE not preserved (950171) - // - const char* doctype = - "" - "" - "" - "" - ""; - - TiXmlDocument doc; - doc.Parse(doctype); - doc.SaveFile("test7.xml"); - doc.Clear(); - doc.LoadFile("test7.xml"); - - TiXmlHandle docH(&doc); - TiXmlUnknown* unknown = docH.Child(1).Unknown(); - XmlTest("Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value()); - #ifdef TIXML_USE_STL - TiXmlNode* node = docH.Child(2).Node(); - std::string str; - str << (*node); - XmlTest("Correct streaming of unknown.", "", str.c_str()); - #endif - } - - { - // [ 791411 ] Formatting bug - // Comments do not stream out correctly. - const char* doctype = - ""; - TiXmlDocument doc; - doc.Parse(doctype); - - TiXmlHandle docH(&doc); - TiXmlComment* comment = docH.Child(0).Node()->ToComment(); - - XmlTest("Comment formatting.", " Somewhat ", comment->Value()); - #ifdef TIXML_USE_STL - std::string str; - str << (*comment); - XmlTest("Comment streaming.", "", str.c_str()); - #endif - } - - { - // [ 870502 ] White space issues - TiXmlDocument doc; - TiXmlText* text; - TiXmlHandle docH(&doc); - - const char* doctype0 = " This has leading and trailing space "; - const char* doctype1 = "This has internal space"; - const char* doctype2 = " This has leading, trailing, and internal space "; - - TiXmlBase::SetCondenseWhiteSpace(false); - doc.Clear(); - doc.Parse(doctype0); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", " This has leading and trailing space ", text->Value()); - - doc.Clear(); - doc.Parse(doctype1); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", "This has internal space", text->Value()); - - doc.Clear(); - doc.Parse(doctype2); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", " This has leading, trailing, and internal space ", text->Value()); - - TiXmlBase::SetCondenseWhiteSpace(true); - doc.Clear(); - doc.Parse(doctype0); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has leading and trailing space", text->Value()); - - doc.Clear(); - doc.Parse(doctype1); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has internal space", text->Value()); - - doc.Clear(); - doc.Parse(doctype2); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has leading, trailing, and internal space", text->Value()); - } - - { - // Double attributes - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse(doctype); - - XmlTest("Parsing repeated attributes.", 0, (int)doc.Error()); // not an error to tinyxml - XmlTest("Parsing repeated attributes.", "blue", doc.FirstChildElement("element")->Attribute("attr")); - } - - { - // Embedded null in stream. - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse(doctype); - XmlTest("Embedded null throws error.", true, doc.Error()); - - #ifdef TIXML_USE_STL - istringstream strm(doctype); - doc.Clear(); - doc.ClearError(); - strm >> doc; - XmlTest("Embedded null throws error.", true, doc.Error()); - #endif - } - - { - // Legacy mode test. (This test may only pass on a western system) - const char* str = - "" - "<ä>" - "CöntäntßäöüÄÖÜ" - ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle aHandle = docHandle.FirstChildElement("ä"); - TiXmlHandle tHandle = aHandle.Child(0); - assert(aHandle.Element()); - assert(tHandle.Text()); - XmlTest("ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value()); - } - - { - // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 - const char* str = " "; - TiXmlDocument doc; - doc.Parse(str); - XmlTest("Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId()); - } - #ifndef TIXML_USE_STL - { - // String equality. [ 1006409 ] string operator==/!= no worky in all cases - TiXmlString temp; - XmlTest("Empty tinyxml string compare equal", (temp == ""), true); - - TiXmlString foo; - TiXmlString bar(""); - XmlTest("Empty tinyxml string compare equal", (foo == bar), true); - } - - #endif - { - // Bug [ 1195696 ] from marlonism - TiXmlBase::SetCondenseWhiteSpace(false); - TiXmlDocument xml; - xml.Parse("This hangs"); - XmlTest("Test safe error return.", xml.Error(), false); - } - - { - // Bug [ 1243992 ] - another infinite loop - TiXmlDocument doc; - doc.SetCondenseWhiteSpace(false); - doc.Parse("

test

"); - } - { - // Low entities - TiXmlDocument xml; - xml.Parse(""); - const char result[] = { 0x0e, 0 }; - XmlTest("Low entities.", xml.FirstChildElement()->GetText(), result); - xml.Print(); - } - { - // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly - TiXmlDocument xml; - xml.Parse(""); - XmlTest("Throw error with bad end quotes.", xml.Error(), true); - } - #ifdef TIXML_USE_STL - { - // Bug [ 1449463 ] Consider generic query - TiXmlDocument xml; - xml.Parse(""); - - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - float f; - bool b; - //std::string str; - - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &d), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &i), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &f), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &b), TIXML_WRONG_TYPE); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("nobar", &b), TIXML_NO_ATTRIBUTE); - //XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); - - XmlTest("QueryValueAttribute", (d == 3.0), true); - XmlTest("QueryValueAttribute", (i == 3), true); - XmlTest("QueryValueAttribute", (f == 3.0f), true); - //XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); - } - #endif - - #ifdef TIXML_USE_STL - { - // [ 1505267 ] redundant malloc in TiXmlElement::Attribute - TiXmlDocument xml; - xml.Parse(""); - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - - std::string bar = "bar"; - - const std::string* atrrib = ele->Attribute(bar); - ele->Attribute(bar, &d); - ele->Attribute(bar, &i); - - XmlTest("Attribute", atrrib->empty(), false); - XmlTest("Attribute", (d == 3.0), true); - XmlTest("Attribute", (i == 3), true); - } - #endif - - { - // [ 1356059 ] Allow TiXMLDocument to only be at the top level - TiXmlDocument xml, xml2; - xml.InsertEndChild(xml2); - XmlTest("Document only at top level.", xml.Error(), true); - XmlTest("Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY); - } - - { - // [ 1663758 ] Failure to report error on bad XML - TiXmlDocument xml; - xml.Parse(""); - XmlTest("Missing end tag at end of input", xml.Error(), true); - xml.Parse(" "); - XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); - } - - { - // [ 1635701 ] fail to parse files with a tag separated into two lines - // I'm not sure this is a bug. Marked 'pending' for feedback. - TiXmlDocument xml; - xml.Parse("<p>text</p\n><title>"); - //xml.Print(); - //XmlTest( "Tag split by newline", xml.Error(), false ); - } - - #ifdef TIXML_USE_STL - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - istringstream parse1("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->"); - parse1 >> xml; - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest("Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true); - XmlTest("Comments ignore entities.", " far & away ", c1->Value(), true); - } - #endif - - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - xml.Parse("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->"); - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest("Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true); - XmlTest("Comments ignore entities.", " far & away ", c1->Value(), true); - } - /* - { - TiXmlDocument xml; - xml.Parse( "<tag>/</tag>" ); - xml.Print(); - xml.FirstChild()->Print( stdout, 0 ); - xml.FirstChild()->Type(); - } - */ - - /* 1417717 experiment - { - TiXmlDocument xml; - xml.Parse("<text>Dan & Tracie</text>"); - xml.Print(stdout); - } - { - TiXmlDocument xml; - xml.Parse("<text>Dan &foo; Tracie</text>"); - xml.Print(stdout); - } - */ - #if defined(WIN32) && defined(TUNE) - _CrtMemCheckpoint(&endMemState); - //_CrtMemDumpStatistics( &endMemState ); - - _CrtMemState diffMemState; - _CrtMemDifference(&diffMemState, &startMemState, &endMemState); - _CrtMemDumpStatistics(&diffMemState); - #endif - - printf ("\nPass %d, Fail %d\n", gPass, gFail); - return gFail; -} - - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat b/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat deleted file mode 100644 index ba6badf0c0..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat +++ /dev/null @@ -1,16 +0,0 @@ -@echo off -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM -REM -REM Original file Copyright Crytek GMBH or its affiliates, used under license. -REM - -dir Cache /a:-d /s /b >dir.txt \ No newline at end of file diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake +++ /dev/null @@ -1,12 +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. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake deleted file mode 100644 index 5963f882c3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake +++ /dev/null @@ -1,15 +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. -# - -set(LY_COMPILE_OPTIONS - PRIVATE - -fexceptions -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake deleted file mode 100644 index 74ca22aaea..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake +++ /dev/null @@ -1,15 +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. -# - -set(LY_COMPILE_OPTIONS - PRIVATE - /EHsc -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake +++ /dev/null @@ -1,12 +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. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake +++ /dev/null @@ -1,10 +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. -# diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake deleted file mode 100644 index 6fa34f74b4..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake +++ /dev/null @@ -1,12 +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. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED TRUE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake deleted file mode 100644 index c46eb1cb4e..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake +++ /dev/null @@ -1,15 +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. -# - -set(LY_RUNTIME_DEPENDENCIES - 3rdParty::DirectXShaderCompiler::dxcGL - 3rdParty::DirectXShaderCompiler::dxcMetal -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake deleted file mode 100644 index 6fa34f74b4..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake +++ /dev/null @@ -1,12 +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. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED TRUE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake deleted file mode 100644 index 9bb1423231..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake +++ /dev/null @@ -1,44 +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. -# - -set(LY_RUNTIME_DEPENDENCIES - 3rdParty::DirectXShaderCompiler::dxcGL - 3rdParty::DirectXShaderCompiler::dxcMetal -) - -file(TO_CMAKE_PATH "$ENV{ProgramFiles\(x86\)}" program_files_path) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCD3D11/v006 - FILES - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/fxc.exe" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcompiler_47.dll" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcsx_47.dll" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcsxd_47.dll" -) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCGL/V006 - FILES - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGL/V006/D3DCompiler_47.dll" - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGL/V006/HLSLcc.exe" -) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCGMETAL/HLSLcc - FILES - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGMETAL/HLSLcc/HLSLcc_d.exe" - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGMETAL/HLSLcc/HLSLcc.exe" -) - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake +++ /dev/null @@ -1,12 +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. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake deleted file mode 100644 index a6510a297f..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake +++ /dev/null @@ -1,10 +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. -# \ No newline at end of file diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake deleted file mode 100644 index b57c6a3dfe..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - CrySCompileServer.cpp - Core/Common.h - Core/Error.cpp - Core/Error.hpp - Core/WindowsAPIImplementation.h - Core/WindowsAPIImplementation.cpp - Core/Mailer.cpp - Core/Mailer.h - Core/MD5.hpp - Core/StdTypes.hpp - Core/STLHelper.cpp - Core/STLHelper.hpp - Core/Server/CrySimpleCache.cpp - Core/Server/CrySimpleCache.hpp - Core/Server/CrySimpleErrorLog.cpp - Core/Server/CrySimpleErrorLog.hpp - Core/Server/CrySimpleFileGuard.hpp - Core/Server/CrySimpleHTTP.cpp - Core/Server/CrySimpleHTTP.hpp - Core/Server/CrySimpleJob.cpp - Core/Server/CrySimpleJob.hpp - Core/Server/CrySimpleJobCache.cpp - Core/Server/CrySimpleJobCache.hpp - Core/Server/CrySimpleJobCompile.cpp - Core/Server/CrySimpleJobCompile.hpp - Core/Server/CrySimpleJobCompile1.cpp - Core/Server/CrySimpleJobCompile1.hpp - Core/Server/CrySimpleJobCompile2.cpp - Core/Server/CrySimpleJobCompile2.hpp - Core/Server/CrySimpleJobRequest.cpp - Core/Server/CrySimpleJobRequest.hpp - Core/Server/CrySimpleJobGetShaderList.cpp - Core/Server/CrySimpleJobGetShaderList.hpp - Core/Server/CrySimpleMutex.cpp - Core/Server/CrySimpleMutex.hpp - Core/Server/CrySimpleServer.cpp - Core/Server/CrySimpleServer.hpp - Core/Server/CrySimpleSock.cpp - Core/Server/CrySimpleSock.hpp - Core/Server/ShaderList.cpp - Core/Server/ShaderList.hpp - External/tinyxml/tinystr.cpp - External/tinyxml/tinystr.h - External/tinyxml/tinyxml.cpp - External/tinyxml/tinyxml.h - External/tinyxml/tinyxmlerror.cpp - External/tinyxml/tinyxmlparser.cpp -) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h new file mode 100644 index 0000000000..a4dba9229e --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -0,0 +1,46 @@ +/* + * 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 <AzCore/Debug/TraceMessageBus.h> +#include <AzCore/std/containers/list.h> +#include <AzCore/std/string/string.h> + +namespace AtomToolsFramework +{ + // Records all TraceMessageBus activity to a string + class TraceRecorder : private AZ::Debug::TraceMessageBus::Handler + { + public: + AZ_TYPE_INFO(AtomToolsFramework::TraceRecorder, "{7B49AFD0-D0AB-4CB7-A4B5-6D88D30DCBFD}"); + + TraceRecorder(size_t maxMessageCount = std::numeric_limits<size_t>::max()); + ~TraceRecorder(); + + //! Get the combined output of all messages + AZStd::string GetDump() const; + + private: + ////////////////////////////////////////////////////////////////////////// + // AZ::Debug::TraceMessageBus::Handler overrides... + bool OnAssert(const char* /*message*/) override; + bool OnException(const char* /*message*/) override; + bool OnError(const char* /*window*/, const char* /*message*/) override; + bool OnWarning(const char* /*window*/, const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + ////////////////////////////////////////////////////////////////////////// + + size_t m_maxMessageCount = std::numeric_limits<size_t>::max(); + AZStd::list<AZStd::string> m_messages; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp new file mode 100644 index 0000000000..e08dd3e48a --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp @@ -0,0 +1,81 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include <AtomToolsFramework/Debug/TraceRecorder.h> +#include <AzCore/StringFunc/StringFunc.h> + +namespace AtomToolsFramework +{ + TraceRecorder::TraceRecorder(size_t maxMessageCount) + : m_maxMessageCount(maxMessageCount) + { + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + } + + TraceRecorder::~TraceRecorder() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + AZStd::string TraceRecorder::GetDump() const + { + AZStd::string dump; + AZ::StringFunc::Join(dump, m_messages.begin(), m_messages.end(), "\n"); + return dump; + } + + bool TraceRecorder::OnAssert(const char* message) + { + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Assert: %s", message)); + } + return false; + } + + bool TraceRecorder::OnException(const char* message) + { + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Exception: %s", message)); + } + return false; + } + + bool TraceRecorder::OnError(const char* /*window*/, const char* message) + { + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Error: %s", message)); + } + return false; + } + + bool TraceRecorder::OnWarning(const char* /*window*/, const char* message) + { + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Warning: %s", message)); + } + return false; + } + + bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message) + { + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("%s", message)); + } + return false; + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 8c0ca71b78..e8539711f7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -10,6 +10,7 @@ # set(FILES + Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -21,6 +22,7 @@ set(FILES Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h + Source/Debug/TraceRecorder.cpp Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp Source/Inspector/InspectorWidget.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 234afc6e27..2fd1aac211 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -12,32 +12,29 @@ #include <Document/MaterialDocumentSystemComponent.h> -#include <AzCore/Serialization/SerializeContext.h> -#include <AzCore/Serialization/EditContext.h> -#include <AzCore/RTTI/BehaviorContext.h> - -#include <AzFramework/Asset/AssetSystemBus.h> - -#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> -#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> -#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> -#include <AzToolsFramework/API/ViewPaneOptions.h> -#include <AzToolsFramework/API/EditorAssetSystemAPI.h> -#include <AtomToolsFramework/Util/Util.h> - +#include <Atom/Document/MaterialDocumentNotificationBus.h> +#include <Atom/Document/MaterialDocumentRequestBus.h> +#include <Atom/Document/MaterialDocumentSystemRequestBus.h> #include <Atom/RPI.Edit/Material/MaterialSourceData.h> #include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> - -#include <Atom/Document/MaterialDocumentSystemRequestBus.h> -#include <Atom/Document/MaterialDocumentRequestBus.h> -#include <Atom/Document/MaterialDocumentNotificationBus.h> +#include <AtomToolsFramework/Debug/TraceRecorder.h> +#include <AtomToolsFramework/Util/Util.h> +#include <AzCore/RTTI/BehaviorContext.h> +#include <AzCore/Serialization/EditContext.h> +#include <AzCore/Serialization/SerializeContext.h> +#include <AzFramework/Asset/AssetSystemBus.h> +#include <AzToolsFramework/API/EditorAssetSystemAPI.h> +#include <AzToolsFramework/API/ViewPaneOptions.h> +#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> +#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> +#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include <QApplication> +#include <QFileDialog> +#include <QMessageBox> #include <QString> #include <QStyle> -#include <QMessageBox> -#include <QFileDialog> AZ_POP_DISABLE_WARNING namespace MaterialEditor @@ -212,11 +209,15 @@ namespace MaterialEditor QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -232,11 +233,15 @@ namespace MaterialEditor QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -308,11 +313,15 @@ namespace MaterialEditor } } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool closeResult = true; MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close); if (!closeResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be closed:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -370,11 +379,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -396,11 +409,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -422,11 +439,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -476,19 +497,27 @@ namespace MaterialEditor } } + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); + AZ::Uuid documentId = AZ::Uuid::CreateNull(); MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument); if (documentId.IsNull()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be created:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } + traceRecorder.GetDump().clear(); + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h index 933a3351ba..b6c541421d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h @@ -98,5 +98,6 @@ namespace MaterialEditor AZStd::unordered_set<AZ::Uuid> m_documentIdsToRebuild; AZStd::unordered_set<AZ::Uuid> m_documentIdsToReopen; AZStd::unique_ptr<MaterialEditorSettings> m_settings; + const size_t m_maxMessageBoxLineCount = 15; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp deleted file mode 100644 index 39654af211..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include <QApplication> -#include <QClipboard> -#include <QMenu> -#include <QInputDialog> -#include <QMessageBox> -#include <QFileDialog> -#include <QDesktopServices> - -#include <AzQtComponents/Utilities/DesktopUtilities.h> - -#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> -#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> -#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> -#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h> -#include <AtomToolsFramework/Util/Util.h> - -#include <Atom/Document/MaterialDocumentSystemRequestBus.h> - -#include <Source/Window/MaterialBrowserInteractions.h> -#include <Window/CreateMaterialDialog/CreateMaterialDialog.h> - -#include <Atom/RPI.Reflect/Material/MaterialAsset.h> -#include <Atom/RPI.Edit/Material/MaterialSourceData.h> -#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> - -namespace MaterialEditor -{ - MaterialBrowserInteractions::MaterialBrowserInteractions() - { - using namespace AzToolsFramework::AssetBrowser; - - AssetBrowserInteractionNotificationBus::Handler::BusConnect(); - } - - MaterialBrowserInteractions::~MaterialBrowserInteractions() - { - AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); - } - - void MaterialBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries) - { - AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); - if (!entry) - { - return; - } - - m_caller = caller; - QObject::connect(m_caller, &QObject::destroyed, [this]() - { - m_caller = nullptr; - }); - - AddGenericContextMenuActions(caller, menu, entry); - - if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) - { - const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry); - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) - { - AddContextMenuActionsForMaterialSource(caller, menu, source); - } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) - { - AddContextMenuActionsForMaterialTypeSource(caller, menu, source); - } - else - { - AddContextMenuActionsForOtherSource(caller, menu, source); - } - } - else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) - { - const auto folder = azalias_cast<const FolderAssetBrowserEntry*>(entry); - AddContextMenuActionsForFolder(caller, menu, folder); - } - } - - void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) - { - menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() - { - QApplication::clipboard()->setText(entry->GetName().c_str()); - }); - menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() - { - QApplication::clipboard()->setText(entry->GetFullPath().c_str()); - }); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Child Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - menu->addSeparator(); - - QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() - { - AZ_UNUSED(entry); - // ToDo - }); - openParentAction->setEnabled(false); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) - { - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); - QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() - { - bool ok; - QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); - if (ok) - { - if (newFolderName.isEmpty()) - { - QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); - msgBox.exec(); - } - else - { - AZStd::string newFolderPath; - AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); - QDir dir(newFolderPath.c_str()); - if (dir.exists()) - { - QMessageBox::critical(caller, "Error", "Folder with this name already exists"); - return; - } - auto result = dir.mkdir(newFolderPath.c_str()); - if (!result) - { - AZ_Error("MaterialBrowser", false, "Failed to make new folder"); - return; - } - } - } - }); - - menu->addSeparator(); - - QAction* createMaterialAction = menu->addAction(QObject::tr("Create Material...")); - QObject::connect(createMaterialAction, &QAction::triggered, caller, [caller, entry]() - { - CreateMaterialDialog createDialog(entry->GetFullPath().c_str(), caller); - createDialog.adjustSize(); - - if (createDialog.exec() == QDialog::Accepted && - !createDialog.m_materialFileInfo.absoluteFilePath().isEmpty() && - !createDialog.m_materialTypeFileInfo.absoluteFilePath().isEmpty()) - { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - createDialog.m_materialTypeFileInfo.absoluteFilePath().toUtf8().constData(), - createDialog.m_materialFileInfo.absoluteFilePath().toUtf8().constData()); - } - }); - } - - void MaterialBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) - { - using namespace AzToolsFramework; - - bool isActive = false; - SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); - - if (isActive) - { - menu->addSeparator(); - - AZStd::string path = entry->GetFullPath(); - AzFramework::StringFunc::Path::Normalize(path); - - QMenu* sourceControlMenu = menu->addMenu("Source Control"); - - // Update the enabled state of source control menu actions only if menu is shown - QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), - [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); - }); - - // add get latest action - m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), - [](bool, const SourceControlFileInfo&) {}); - }); - QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() - { - m_getLatestAction = nullptr; - }); - m_getLatestAction->setEnabled(false); - - // add add action - m_addAction = sourceControlMenu->addAction("Add", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_addAction, &QObject::destroyed, [this]() - { - m_addAction = nullptr; - }); - m_addAction->setEnabled(false); - - // add checkout action - m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() - { - m_checkOutAction = nullptr; - }); - m_checkOutAction->setEnabled(false); - - // add undo checkout action - m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() - { - m_undoCheckOutAction = nullptr; - }); - m_undoCheckOutAction->setEnabled(false); - } - } - - void MaterialBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) - { - if (!success && m_caller) - { - QMessageBox::critical(m_caller, "Error", "Source control operation failed."); - } - if (m_getLatestAction) - { - m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); - } - if (m_addAction) - { - m_addAction->setEnabled(!info.IsManaged()); - } - if (m_checkOutAction) - { - m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); - } - if (m_undoCheckOutAction) - { - m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); - } - } -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp new file mode 100644 index 0000000000..92e02d5b42 --- /dev/null +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp @@ -0,0 +1,358 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include <QApplication> +#include <QClipboard> +#include <QMenu> +#include <QInputDialog> +#include <QMessageBox> +#include <QFileDialog> +#include <QDesktopServices> + +#include <AzCore/std/string/wildcard.h> +#include <AzQtComponents/Utilities/DesktopUtilities.h> + +#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> +#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> +#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> +#include <AzToolsFramework/Thumbnails/SourceControlThumbnail.h> +#include <AtomToolsFramework/Util/Util.h> + +#include <Atom/RPI.Edit/Common/AssetUtils.h> +#include <Atom/Document/MaterialDocumentSystemRequestBus.h> + +#include <WIndow/MaterialEditorBrowserInteractions.h> + +#include <Atom/RPI.Reflect/Material/MaterialAsset.h> +#include <Atom/RPI.Edit/Material/MaterialSourceData.h> +#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> + +namespace MaterialEditor +{ + MaterialEditorBrowserInteractions::MaterialEditorBrowserInteractions() + { + using namespace AzToolsFramework::AssetBrowser; + + AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialEditorBrowserInteractions::~MaterialEditorBrowserInteractions() + { + AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries) + { + AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); + if (!entry) + { + return; + } + + m_caller = caller; + QObject::connect(m_caller, &QObject::destroyed, [this]() + { + m_caller = nullptr; + }); + + AddGenericContextMenuActions(caller, menu, entry); + + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) + { + const auto source = azalias_cast<const SourceAssetBrowserEntry*>(entry); + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + { + AddContextMenuActionsForMaterialSource(caller, menu, source); + } + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + { + AddContextMenuActionsForMaterialTypeSource(caller, menu, source); + } + else + { + AddContextMenuActionsForOtherSource(caller, menu, source); + } + } + else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) + { + const auto folder = azalias_cast<const FolderAssetBrowserEntry*>(entry); + AddContextMenuActionsForFolder(caller, menu, folder); + } + } + + void MaterialEditorBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetName().c_str()); + }); + menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetFullPath().c_str()); + }); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Child Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + menu->addSeparator(); + + QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() + { + AZ_UNUSED(entry); + // ToDo + }); + openParentAction->setEnabled(false); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); + QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() + { + bool ok; + QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); + if (ok) + { + if (newFolderName.isEmpty()) + { + QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); + msgBox.exec(); + } + else + { + AZStd::string newFolderPath; + AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); + QDir dir(newFolderPath.c_str()); + if (dir.exists()) + { + QMessageBox::critical(caller, "Error", "Folder with this name already exists"); + return; + } + auto result = dir.mkdir(newFolderPath.c_str()); + if (!result) + { + AZ_Error("MaterialBrowser", false, "Failed to make new folder"); + return; + } + } + } + }); + } + + void MaterialEditorBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + using namespace AzToolsFramework; + + bool isActive = false; + SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); + + if (isActive) + { + menu->addSeparator(); + + AZStd::string path = entry->GetFullPath(); + AzFramework::StringFunc::Path::Normalize(path); + + QMenu* sourceControlMenu = menu->addMenu("Source Control"); + + // Update the enabled state of source control menu actions only if menu is shown + QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), + [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); + }); + + // add get latest action + m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), + [](bool, const SourceControlFileInfo&) {}); + }); + QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() + { + m_getLatestAction = nullptr; + }); + m_getLatestAction->setEnabled(false); + + // add add action + m_addAction = sourceControlMenu->addAction("Add", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_addAction, &QObject::destroyed, [this]() + { + m_addAction = nullptr; + }); + m_addAction->setEnabled(false); + + // add checkout action + m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() + { + m_checkOutAction = nullptr; + }); + m_checkOutAction->setEnabled(false); + + // add undo checkout action + m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() + { + m_undoCheckOutAction = nullptr; + }); + m_undoCheckOutAction->setEnabled(false); + } + } + + void MaterialEditorBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) + { + if (!success && m_caller) + { + QMessageBox::critical(m_caller, "Error", "Source control operation failed."); + } + if (m_getLatestAction) + { + m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); + } + if (m_addAction) + { + m_addAction->setEnabled(!info.IsManaged()); + } + if (m_checkOutAction) + { + m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); + } + if (m_undoCheckOutAction) + { + m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); + } + } +} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h similarity index 91% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h rename to Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h index 2806cee6d4..7ee3ec833d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h @@ -31,14 +31,14 @@ namespace AzToolsFramework namespace MaterialEditor { - class MaterialBrowserInteractions + class MaterialEditorBrowserInteractions : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler { public: - AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(MaterialEditorBrowserInteractions, AZ::SystemAllocator, 0); - MaterialBrowserInteractions(); - ~MaterialBrowserInteractions(); + MaterialEditorBrowserInteractions(); + ~MaterialEditorBrowserInteractions(); private: //! AssetBrowserInteractionNotificationBus::Handler overrides... diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 6f03510301..a1ff8da635 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -98,7 +98,7 @@ namespace MaterialEditor void MaterialEditorWindowComponent::CreateMaterialEditorWindow() { - m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); + m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions); m_window.reset(aznew MaterialEditorWindow); m_window->show(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h index f727fcc97c..1ea05d6530 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h @@ -16,7 +16,7 @@ #include <AzToolsFramework/API/EditorWindowRequestBus.h> #include <Atom/Window/MaterialEditorWindowFactoryRequestBus.h> -#include <Source/Window/MaterialBrowserInteractions.h> +#include <Source/Window/MaterialEditorBrowserInteractions.h> #include <Source/Window/MaterialEditorWindow.h> namespace MaterialEditor @@ -57,6 +57,6 @@ namespace MaterialEditor //////////////////////////////////////////////////////////////////////// AZStd::unique_ptr<MaterialEditorWindow> m_window; - AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions; + AZStd::unique_ptr<MaterialEditorBrowserInteractions> m_materialEditorBrowserInteractions; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index fef3aeefb7..1547dbf48f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -14,8 +14,8 @@ set(FILES Include/Atom/Window/MaterialEditorWindowNotificationBus.h Include/Atom/Window/MaterialEditorWindowRequestBus.h Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h - Source/Window/MaterialBrowserInteractions.h - Source/Window/MaterialBrowserInteractions.cpp + Source/Window/MaterialEditorBrowserInteractions.h + Source/Window/MaterialEditorBrowserInteractions.cpp Source/Window/MaterialEditorWindow.h Source/Window/MaterialEditorWindow.cpp Source/Window/MaterialEditorWindowModule.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index 82f65b205d..94dfb39419 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -100,6 +100,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect(); SetupThumbnails(); + m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); } void EditorMaterialSystemComponent::Deactivate() @@ -111,6 +112,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect(); TeardownThumbnails(); + m_materialBrowserInteractions.reset(); if (m_openMaterialEditorAction) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index de065f679e..09ad1c1b9c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -22,6 +22,8 @@ #include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h> +#include <Material/MaterialBrowserInteractions.h> + namespace AZ { namespace Render @@ -76,6 +78,8 @@ namespace AZ AzFramework::TargetInfo m_materialEditorTarget; QAction* m_openMaterialEditorAction = nullptr; + + AZStd::unique_ptr<MaterialBrowserInteractions> m_materialBrowserInteractions; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp new file mode 100644 index 0000000000..82fa47a810 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include <AzCore/std/string/wildcard.h> +#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> +#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h> +#include <Material/MaterialBrowserInteractions.h> + +namespace AZ +{ + namespace Render + { + MaterialBrowserInteractions::MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialBrowserInteractions::~MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialBrowserInteractions::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) + { + if (HandlesSource(fullSourceFileName)) + { + openers.push_back( + { + "Material_Editor", + "Open in Material Editor...", + QIcon(), + [&](const char* fullSourceFileNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID) + { + EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, fullSourceFileNameInCallback); + } + }); + } + } + + bool MaterialBrowserInteractions::HandlesSource(AZStd::string_view fileName) const + { + return AZStd::wildcard_match("*.material", fileName.data()); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h new file mode 100644 index 0000000000..bd9791d3a5 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h @@ -0,0 +1,52 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> +#include <AzToolsFramework/SourceControl/SourceControlAPI.h> + +class QWidget; +class QMenu; +class QAction; + +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserEntry; + class SourceAssetBrowserEntry; + class FolderAssetBrowserEntry; + } +} + +namespace AZ +{ + namespace Render + { + class MaterialBrowserInteractions + : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + + MaterialBrowserInteractions(); + ~MaterialBrowserInteractions(); + + private: + //! AssetBrowserInteractionNotificationBus::Handler overrides... + void AddSourceFileOpeners(const char* fullSourceFileName, const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) override; + + bool HandlesSource(AZStd::string_view fileName) const; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index f77b175cd7..fe475da189 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -41,6 +41,8 @@ set(FILES Source/Material/EditorMaterialModelUvNameMapInspector.h Source/Material/EditorMaterialSystemComponent.cpp Source/Material/EditorMaterialSystemComponent.h + Source/Material/MaterialBrowserInteractions.h + Source/Material/MaterialBrowserInteractions.cpp Source/Material/MaterialThumbnail.cpp Source/Material/MaterialThumbnail.h Source/Mesh/EditorMeshComponent.h diff --git a/Gems/Camera/Code/Source/Camera_precompiled.h b/Gems/Camera/Code/Source/Camera_precompiled.h index 028ff586c6..2016c4b411 100644 --- a/Gems/Camera/Code/Source/Camera_precompiled.h +++ b/Gems/Camera/Code/Source/Camera_precompiled.h @@ -26,7 +26,6 @@ // Editor ///////////////////////////////////////////////////////////////////////////// #include <EditorDefs.h> -#include <EditTool.h> #include <Resource.h> ///////////////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp index 6b8b22f78c..c10e3b06e2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp @@ -119,9 +119,7 @@ namespace EMStudio mDock->setFeatures(features); - // mDock->setFloating( true ); mainWindow->addDockWidget(Qt::RightDockWidgetArea, mDock); - mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); // put tabs on top? return mDock; } @@ -139,4 +137,4 @@ namespace EMStudio return widget; } -} // namespace EMStudio \ No newline at end of file +} // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index 5adec5e0a4..496b6b8e94 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -1866,6 +1866,12 @@ namespace EMStudio // add each layout in the remove menu for (uint32 i = 0; i < numLayoutNames; ++i) { + // User cannot remove the default layout. This layout is referenced in the qrc file, removing it will + // cause compiling issue too. + if (mLayoutNames[i] == "AnimGraph") + { + continue; + } QAction* action = removeMenu->addAction(mLayoutNames[i].c_str()); connect(action, &QAction::triggered, this, &MainWindow::OnRemoveLayout); } diff --git a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h b/Gems/LyShine/Code/Editor/ViewportDragInteraction.h index f7574900a2..477720d0a2 100644 --- a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h +++ b/Gems/LyShine/Code/Editor/ViewportDragInteraction.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 diff --git a/Gems/LyShine/Code/Editor/ViewportHelpers.h b/Gems/LyShine/Code/Editor/ViewportHelpers.h index d128603171..9a1aadead5 100644 --- a/Gems/LyShine/Code/Editor/ViewportHelpers.h +++ b/Gems/LyShine/Code/Editor/ViewportHelpers.h @@ -11,6 +11,8 @@ */ #pragma once +#include <LyShine/Draw2d.h> + namespace ViewportHelpers { //------------------------------------------------------------------------------- diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index 5ce2bf37f7..1e137fe91b 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -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 } diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.h b/Gems/LyShine/Code/Editor/ViewportIcon.h index 5f72c7562a..85fd2fe068 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.h +++ b/Gems/LyShine/Code/Editor/ViewportIcon.h @@ -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; }; diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.cpp b/Gems/LyShine/Code/Editor/ViewportWidget.cpp index c805d45bef..2b1ea16c97 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.cpp +++ b/Gems/LyShine/Code/Editor/ViewportWidget.cpp @@ -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 diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.h b/Gems/LyShine/Code/Editor/ViewportWidget.h index e506a26d88..4d15f3dea4 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.h +++ b/Gems/LyShine/Code/Editor/ViewportWidget.h @@ -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; }; diff --git a/Gems/LyShine/Code/Include/LyShine/Draw2d.h b/Gems/LyShine/Code/Include/LyShine/Draw2d.h new file mode 100644 index 0000000000..ec636c3e3b --- /dev/null +++ b/Gems/LyShine/Code/Include/LyShine/Draw2d.h @@ -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; +}; diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 4beba0b1eb..cd15475039 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -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; + + AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); } //////////////////////////////////////////////////////////////////////////////////////////////////// CDraw2d::~CDraw2d() { + AZ::Render::Bootstrap::NotificationBus::Handler::BusDisconnect(); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::BeginDraw2d(bool deferCalls) +void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) { - IRenderer* renderer = gEnv->pRenderer; - AZ::Vector2 viewportSize( - static_cast<float>(renderer->GetOverlayWidth()), - static_cast<float>(renderer->GetOverlayHeight())); - BeginDraw2d(viewportSize, deferCalls); -} + // At this point the RPI is ready for use -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls) -{ - // 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 + // 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); - // Push the current state of the m_deferCalls onto a stack to support nested calls - m_deferCallsFlagStack.push(m_deferCalls); - - m_deferCalls = deferCalls; - - // 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(); } + AZ_Assert(scene != nullptr, "Attempting to create a DynamicDrawContext for a viewport context that has not been associated with a scene yet."); - // unwind the nesting stack - m_deferCalls = m_deferCallsFlagStack.top(); - m_deferCallsFlagStack.pop(); + // 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 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); + // 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(); + } - // This will end up using DrawPrimitive to render the quad - renderer->DrawDynVB(vertices, nullptr, NUM_VERTS, 0, prtLineList); + if (imageView) + { + drawSrg->SetImageView(shaderData.m_imageInputIndex, imageView, 0); + } + + // 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); } diff --git a/Gems/LyShine/Code/Source/Draw2d.h b/Gems/LyShine/Code/Source/Draw2d.h deleted file mode 100644 index a62dc22937..0000000000 --- a/Gems/LyShine/Code/Source/Draw2d.h +++ /dev/null @@ -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; -}; diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index cfea0cbdf7..286e756ffa 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -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 diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index f1ce411d83..5ea01c5c1e 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -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(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - ITexture* texture = GetMonoTestTexture(); - int texId = texture->GetTextureID(); + AZ::Data::Instance<AZ::RPI::Image> texture = GetMonoTestTexture(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - - 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) diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp index f386d5756b..2af773734c 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp @@ -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; diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.h b/Gems/LyShine/Code/Source/UiCanvasComponent.h index 6e59a0899f..3e7171c642 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.h +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.h @@ -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 diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 380095a289..6575a1d2f0 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -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 diff --git a/Gems/LyShine/Code/Source/UiFaderComponent.cpp b/Gems/LyShine/Code/Source/UiFaderComponent.cpp index 96690db7c9..3259da0480 100644 --- a/Gems/LyShine/Code/Source/UiFaderComponent.cpp +++ b/Gems/LyShine/Code/Source/UiFaderComponent.cpp @@ -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> diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index b5b407c421..02ea1467dc 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -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> diff --git a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp index 518be03751..e6cbef8386 100644 --- a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp @@ -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> diff --git a/Gems/LyShine/Code/Source/UiMaskComponent.cpp b/Gems/LyShine/Code/Source/UiMaskComponent.cpp index df49673858..f7452108e7 100644 --- a/Gems/LyShine/Code/Source/UiMaskComponent.cpp +++ b/Gems/LyShine/Code/Source/UiMaskComponent.cpp @@ -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 diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index a718cc8e53..b1092ab92f 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -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" diff --git a/Gems/LyShine/Code/lyshine_static_files.cmake b/Gems/LyShine/Code/lyshine_static_files.cmake index 140debff84..8491a66030 100644 --- a/Gems/LyShine/Code/lyshine_static_files.cmake +++ b/Gems/LyShine/Code/lyshine_static_files.cmake @@ -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 diff --git a/Gems/LyShineExamples/Code/CMakeLists.txt b/Gems/LyShineExamples/Code/CMakeLists.txt index ccf49ba467..372bfa948b 100644 --- a/Gems/LyShineExamples/Code/CMakeLists.txt +++ b/Gems/LyShineExamples/Code/CMakeLists.txt @@ -23,6 +23,7 @@ ly_add_target( PUBLIC Legacy::CryCommon Gem::LmbrCentral + Gem::LyShine.Static ) ly_add_target( diff --git a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp index 4ff8128d47..80750efe7f 100644 --- a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp +++ b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp @@ -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> diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h index bea6de5898..9d8f327616 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h @@ -105,7 +105,7 @@ namespace WhiteBox // create the buffer with the specified data AZ::RPI::BufferAssetCreator bufferAssetCreator; bufferAssetCreator.Begin(AZ::Uuid::CreateRandom()); - bufferAssetCreator.SetUseCommonPool(AZ::RPI::CommonBufferPoolType::DynamicInputAssembly); + bufferAssetCreator.SetUseCommonPool(AZ::RPI::CommonBufferPoolType::StaticInputAssembly); bufferAssetCreator.SetBuffer(data.data(), bufferDescriptor.m_byteCount, bufferDescriptor); bufferAssetCreator.SetBufferViewDescriptor(m_bufferViewDescriptor); diff --git a/cmake/3rdParty/FindDirectXShaderCompiler.cmake b/cmake/3rdParty/FindDirectXShaderCompiler.cmake deleted file mode 100644 index 8973775e48..0000000000 --- a/cmake/3rdParty/FindDirectXShaderCompiler.cmake +++ /dev/null @@ -1,22 +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. -# - -ly_add_external_target( - NAME dxcGL - PACKAGE DirectXShaderCompiler - VERSION 1.0.1-az.1 -) - -ly_add_external_target( - NAME dxcMetal - PACKAGE DirectXShaderCompiler - VERSION 1.0.1-az.1 -) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index 8ab270ec0d..8be3abbf3c 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -25,6 +24,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-android TARGETS freetype PACKAGE_HASH 74dd75382688323c3a2a5090f473840b5d7e9d2aed1a4fcdff05ed2a09a664f2) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-android TARGETS AWSNativeSDK PACKAGE_HASH e2192157534cc8c4e22769545d88dff03ec6c1031599716ef63de3ebbb8c9a44) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-android TARGETS PhysX PACKAGE_HASH 9c494576c2d4ff04dee5a9e092fcd9d5af4b2845f15ffdfcaabb0dbc5b88a7a9) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-android TARGETS mikkelsen PACKAGE_HASH 075e8e4940884971063b5a9963014e2e517246fa269c07c7dc55b8cf2cd99705) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-android TARGETS googletest PACKAGE_HASH 95671be75287a61c9533452835c3647e9c1b30f81b34b43bcb0ec1997cc23894) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 6d3499534c..bd6f8276f7 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -37,6 +36,7 @@ ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGET ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-linux TARGETS AWSNativeSDK PACKAGE_HASH e69c55682638dc1e7fa571a61a82c8a69d395c74a008543a5188f4bd2b6b10c4) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-linux TARGETS PhysX PACKAGE_HASH e3ca36106a8dbf1524709f8bb82d520920ebd3ff3a92672d382efff406c75ee3) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index ff6227f88c..53e7066e99 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -41,6 +40,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-mac TARGETS Lua PACKAGE_HASH d63357a73f9f8f297cf770fa4b92dca1fdd5761d4a2215e38f6e96fa274b28aa) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-mac TARGETS PhysX PACKAGE_HASH 149f5e9b44bd27291b1c4772f5e89a1e0efa88eef73c7e0b188935ed4d0c4a70) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) diff --git a/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake b/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake deleted file mode 100644 index c00f71dbc1..0000000000 --- a/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake +++ /dev/null @@ -1,16 +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. -# - -set(DIRECTXSHADERCOMPILER_BINARY_BASE_PATH ${BASE_PATH}/bin/darwin_x64/$<IF:$<CONFIG:Debug>,debug,release>) - -set(DIRECTXSHADERCOMPILER_DXCGL_RUNTIME_DEPENDENCIES ${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcGL\nCompiler/LLVMGL/$<IF:$<CONFIG:Debug>,debug,release>) - -set(DIRECTXSHADERCOMPILER_DXCMETAL_RUNTIME_DEPENDENCIES ${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcMetal\nCompiler/LLVMMETAL/$<IF:$<CONFIG:Debug>,debug,release>) diff --git a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake index 8cab9da1ba..d6024636bc 100644 --- a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake +++ b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_mac.cmake - DirectXShaderCompiler_mac.cmake FbxSdk_mac.cmake OpenGLInterface_mac.cmake OpenSSL_mac.cmake diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 1e2c80180d..e5993a0dec 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -43,6 +42,7 @@ ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-windows TARGETS PhysX PACKAGE_HASH 198bed89d1aae7caaf5dadba24cee56235fe41725d004b64040d4e50d0f3aa1a) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) diff --git a/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake b/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake deleted file mode 100644 index 2b50bc7f72..0000000000 --- a/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake +++ /dev/null @@ -1,16 +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. -# - -set(DIRECTXSHADERCOMPILER_BINARY_BASE_PATH "${BASE_PATH}/bin/win_x64/$<IF:$<CONFIG:Debug>,debug,release>/") - -set(DIRECTXSHADERCOMPILER_DXCGL_RUNTIME_DEPENDENCIES "${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcGL.exe\nCompiler/LLVMGL/$<IF:$<CONFIG:Debug>,debug,release>") - -set(DIRECTXSHADERCOMPILER_DXCMETAL_RUNTIME_DEPENDENCIES "${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcMetal.exe\nCompiler/LLVMMETAL/$<IF:$<CONFIG:Debug>,debug,release>") diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 25526b7aff..3b42452990 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages_windows.cmake Crashpad_windows.cmake - DirectXShaderCompiler_windows.cmake dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index 7ef0b3b329..43858fa244 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -26,6 +25,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev2-ios TARGETS PhysX PACKAGE_HASH 27e68bd90915dbd0bd5f26cae714e9a137f6b1aa8a8e0bf354a4a9176aa553d5) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googletest PACKAGE_HASH 2f121ad9784c0ab73dfaa58e1fee05440a82a07cc556bec162eeb407688111a7) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index fef363e9e4..9fc90e42e5 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages.cmake FindClang.cmake - FindDirectXShaderCompiler.cmake Finddyad.cmake FindFbxSdk.cmake Findlibav.cmake