Merge remote-tracking branch 'upstream/main' into DisableAtomShim

main
rgba16f 5 years ago
commit 40a35b4e45

@ -157,7 +157,7 @@ endif()
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::BlastTests
TEST_SUITE sandbox
TEST_SUITE periodic
TEST_SERIAL TRUE
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
TIMEOUT 3600

@ -22,6 +22,7 @@ if(CMAKE_VERSION VERSION_EQUAL 3.19)
endif()
include(cmake/Version.cmake)
include(cmake/OutputDirectory.cmake)
if(NOT PROJECT_NAME)
project(O3DE
@ -30,7 +31,7 @@ if(NOT PROJECT_NAME)
)
endif()
include(cmake/Initialize.cmake)
include(cmake/GeneralSettings.cmake)
include(cmake/FileUtil.cmake)
include(cmake/PAL.cmake)
include(cmake/PALTools.cmake)

@ -28,7 +28,7 @@ namespace Physics
class CharacterColliderNodeConfiguration
{
public:
AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
AZ_CLASS_ALLOCATOR_DECL
virtual ~CharacterColliderNodeConfiguration() = default;
@ -42,7 +42,7 @@ namespace Physics
class CharacterColliderConfiguration
{
public:
AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
AZ_CLASS_ALLOCATOR_DECL
virtual ~CharacterColliderConfiguration() = default;
@ -63,21 +63,23 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0);
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
virtual ~CharacterConfiguration() = default;
static void Reflect(AZ::ReflectContext* context);
AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with.
AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on.
MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character.
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior.
float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees.
float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb.
float m_minimumMovementDistance = 0.001f; ///< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; ///< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; ///< Used to identify the collider associated with the character controller.
AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with.
AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on.
MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character.
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior.
float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees.
float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb.
float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller.
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
};
/// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready
@ -88,7 +90,7 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0);
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
~Character() override = default;

@ -29,7 +29,7 @@ namespace AzPhysics
struct SimulatedBodyConfiguration
{
AZ_CLASS_ALLOCATOR_DECL;
AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
static void Reflect(AZ::ReflectContext* context);
SimulatedBodyConfiguration() = default;

@ -246,26 +246,6 @@ namespace Physics
using SystemRequests = System;
using SystemRequestBus = AZ::EBus<SystemRequests, SystemRequestsTraits>;
/// Physics character system global requests.
class CharacterSystemRequests
: public AZ::EBusTraits
{
public:
// EBusTraits
// singleton pattern
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual ~CharacterSystemRequests() = default;
/// Creates the physics representation used to handle basic character interactions (also known as a character
/// controller).
virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig,
const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0;
};
typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus;
/// Physics system global debug requests.
class SystemDebugRequests
: public AZ::EBusTraits

@ -37,6 +37,7 @@ namespace AzFramework
// ViewportControllerInterface ...
bool HandleInputChannelEvent(const ViewportControllerInputEvent& event) override;
void ResetInputChannels() override;
void UpdateViewport(const ViewportControllerUpdateEvent& event) override;
void RegisterViewportContext(ViewportId viewport) override;
void UnregisterViewportContext(ViewportId viewport) override;
@ -58,6 +59,7 @@ namespace AzFramework
ViewportId GetViewportId() const { return m_viewportId; }
virtual bool HandleInputChannelEvent([[maybe_unused]]const ViewportControllerInputEvent& event) { return false; }
virtual void ResetInputChannels() {}
virtual void UpdateViewport([[maybe_unused]]const ViewportControllerUpdateEvent& event) {}
private:

@ -30,6 +30,15 @@ namespace AzFramework
return instanceIt->second->HandleInputChannelEvent(event);
}
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
void MultiViewportController<TViewportControllerInstance, Priority>::ResetInputChannels()
{
for (auto instanceIt = m_instances.begin(); instanceIt != m_instances.end(); ++instanceIt)
{
instanceIt->second->ResetInputChannels();
}
}
template <class TViewportControllerInstance, ViewportControllerPriority Priority>
void MultiViewportController<TViewportControllerInstance, Priority>::UpdateViewport(const ViewportControllerUpdateEvent& event)
{

@ -49,6 +49,11 @@ namespace AzFramework
bool ViewportControllerList::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
if (!IsEnabled())
{
return false;
}
// If our event priority is "custom", we should dispatch at all priority levels in order
using AzFramework::ViewportControllerPriority;
if (event.m_priority == AzFramework::ViewportControllerPriority::DispatchToAllPriorities)
@ -76,6 +81,23 @@ namespace AzFramework
}
}
void ViewportControllerList::ResetInputChannels()
{
// We don't need to send this while we're disabled, we're guaranteed to call ResetInputChannels after being re-enabled.
if (!IsEnabled())
{
return;
}
for (const auto& controllerList : m_controllers)
{
for (const auto& controller : controllerList.second)
{
controller->ResetInputChannels();
}
}
}
bool ViewportControllerList::DispatchInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
if (auto priorityListIt = m_controllers.find(event.m_priority); priorityListIt != m_controllers.end())
@ -106,6 +128,11 @@ namespace AzFramework
void ViewportControllerList::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
if (!IsEnabled())
{
return;
}
// If our event priority is "custom", we should dispatch at all priority levels in reverse order
// Reverse order lets high priority controllers get the last say in viewport update operations
using AzFramework::ViewportControllerPriority;
@ -174,4 +201,22 @@ namespace AzFramework
}
}
}
bool ViewportControllerList::IsEnabled() const
{
return m_enabled;
}
void ViewportControllerList::SetEnabled(bool enabled)
{
if (m_enabled != enabled)
{
m_enabled = enabled;
// If we've been re-enabled, reset our input channels as they may have missed state changes.
if (m_enabled)
{
ResetInputChannels();
}
}
}
} //namespace AzFramework

@ -37,6 +37,9 @@ namespace AzFramework
//! either a controller returns true to consume the event in OnInputChannelEvent or the controller list is exhausted.
//! InputChannelEvents are sent to controllers in priority order (from the lowest priority value to the highest).
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
//! Dispatches a ResetInputChannels call to all controllers registered to this list.
//! Calls to controllers are made in an undefined order.
void ResetInputChannels() override;
//! Dispatches an update tick to all controllers registered to this list.
//! This occurs in *reverse* priority order (i.e. from the highest priority value to the lowest) so that
//! controllers with the highest registration priority may override the transforms of the controllers with the
@ -50,6 +53,12 @@ namespace AzFramework
//! All ViewportControllerLists have a priority of Custom to ensure
//! that they receive events at all priorities from any parent controllers.
AzFramework::ViewportControllerPriority GetPriority() const { return ViewportControllerPriority::DispatchToAllPriorities; }
//! Returns true if this controller list is enabled, i.e.
//! it is accepting and forwarding input and update events to its children.
bool IsEnabled() const;
//! Set this controller list's enabled state.
//! If a controller list is disabled, it will ignore all input and update events rather than dispatching them to its children.
void SetEnabled(bool enabled);
private:
void SortControllers();
@ -58,5 +67,6 @@ namespace AzFramework
AZStd::unordered_map<AzFramework::ViewportControllerPriority, AZStd::vector<ViewportControllerPtr>> m_controllers;
AZStd::unordered_set<ViewportId> m_viewports;
bool m_enabled = true;
};
} //namespace AzFramework

@ -18,6 +18,8 @@
#include <AzCore/std/typetraits/is_enum.h>
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/RTTI/TypeSafeIntegral.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Name/NameDictionary.h>
namespace AzNetworking
{
@ -173,6 +175,22 @@ namespace AzNetworking
return true;
}
};
template<>
struct SerializeObjectHelper<AZ::Name>
{
static bool SerializeObject(ISerializer& serializer, AZ::Name& value)
{
AZ::Name::Hash nameHash = value.GetHash();
bool result = serializer.Serialize(nameHash, "NameHash");
if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject)
{
value = AZ::NameDictionary::Instance().FindName(nameHash);
}
return result;
}
};
}
#include <AzNetworking/Serialization/AzContainerSerializers.h>

@ -2298,6 +2298,12 @@ namespace AzQtComponents
OptimizedSetParent(dock, mainWindow);
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock);
dock->show();
// Make sure we listen for events on the dock widget being put into a floating dock window
// because this might be called programmatically, so the dock widget might have never been
// parented to our m_mainWindow initially, so it won't already have an event filter,
// which will prevent the docking functionality from working.
dock->installEventFilter(this);
}
}

@ -815,8 +815,6 @@ namespace AzToolsFramework
/// Hide or show the circular dependency error when saving slices
virtual void SetShowCircularDependencyError(const bool& /*showCircularDependencyError*/) {}
virtual void SetEditTool(const char* /*tool*/) {}
/// Launches the Lua editor and opens the specified (space separated) files.
virtual void LaunchLuaEditor(const char* /*files*/) {}

@ -491,6 +491,14 @@ namespace AzToolsFramework
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditorBegin);
//cache the current selected entities.
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
//deselect entities if selected when entering game mode before deactivating the entities in StartPlayInEditor(...)
if (!m_selectedBeforeStartingGame.empty())
{
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::MarkEntitiesDeselected, m_selectedBeforeStartingGame);
}
if (m_isLegacySliceService)
{
SliceEditorEntityOwnershipService* editorEntityOwnershipService =
@ -507,8 +515,6 @@ namespace AzToolsFramework
m_isRunningGame = true;
ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities);
EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditor);
}

@ -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)
{

@ -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();
}

@ -1,588 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorDefs.h"
#include "QRollupCtrl.h"
// Qt
#include <QMenu>
#include <QStylePainter>
#include <QVBoxLayout>
#include <QSettings>
#include <QToolButton>
#include <QStyleOptionToolButton>
//////////////////////////////////////////////////////////////////////////
class QRollupCtrlButton
: public QToolButton
{
public:
QRollupCtrlButton(QWidget* parent);
inline void setSelected(bool b) { selected = b; update(); }
inline bool isSelected() const { return selected; }
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
protected:
void paintEvent(QPaintEvent*) override;
private:
bool selected;
};
QRollupCtrlButton::QRollupCtrlButton(QWidget* parent)
: QToolButton(parent)
, selected(true)
{
setBackgroundRole(QPalette::Window);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
setFocusPolicy(Qt::NoFocus);
setStyleSheet("* {margin: 2px 5px 2px 5px; border: 1px solid #CBA457;}");
}
QSize QRollupCtrlButton::sizeHint() const
{
QSize iconSize(8, 8);
if (!icon().isNull())
{
int icone = style()->pixelMetric(QStyle::PM_SmallIconSize);
iconSize += QSize(icone + 2, icone);
}
QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text()) + QSize(0, 8);
QSize total(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height()));
return total.expandedTo(QApplication::globalStrut());
}
QSize QRollupCtrlButton::minimumSizeHint() const
{
if (icon().isNull())
{
return QSize();
}
int icone = style()->pixelMetric(QStyle::PM_SmallIconSize);
return QSize(icone + 8, icone + 8);
}
void QRollupCtrlButton::paintEvent(QPaintEvent*)
{
QStylePainter p(this);
// draw the background manually, not to clash with UI 2.0 style shets
// the numbers here are taken from the stylesheet in the constructor
p.fillRect(QRect(5, 1, width() - 10, height() - 3), QColor(52, 52, 52));
{
QStyleOptionToolButton opt;
initStyleOption(&opt);
if (isSelected())
{
if (opt.state & QStyle::State_MouseOver)
{
opt.state |= QStyle::State_Sunken;
}
opt.state |= QStyle::State_MouseOver;
}
p.drawComplexControl(QStyle::CC_ToolButton, opt);
}
{
p.setPen(QPen(QColor(132, 128, 125)));
int top = height() / 2 - 2;
p.drawLine(2, top, 4, top);
p.drawLine(width() - 5, top, width() - 3, top);
int bottom = !isSelected() ? top + 4 : height();
p.drawLine(2, bottom, 2, top);
p.drawLine(width() - 3, bottom, width() - 3, top);
if (!isSelected())
{
p.drawLine(2, bottom, 4, bottom);
p.drawLine(width() - 5, bottom, width() - 3, bottom);
}
}
}
//////////////////////////////////////////////////////////////////////////
QRollupCtrl::Page* QRollupCtrl::page(QWidget* widget) const
{
if (!widget)
{
return 0;
}
for (PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
{
if ((*i).widget == widget)
{
return (Page*)&(*i);
}
}
return 0;
}
QRollupCtrl::Page* QRollupCtrl::page(int index)
{
if (index >= 0 && index < m_pageList.size())
{
return &m_pageList[index];
}
return 0;
}
const QRollupCtrl::Page* QRollupCtrl::page(int index) const
{
if (index >= 0 && index < m_pageList.size())
{
return &m_pageList.at(index);
}
return 0;
}
inline void QRollupCtrl::Page::setText(const QString& text) { button->setText(text); }
inline void QRollupCtrl::Page::setIcon(const QIcon& is) { button->setIcon(is); }
inline void QRollupCtrl::Page::setToolTip(const QString& tip) { button->setToolTip(tip); }
inline QString QRollupCtrl::Page::text() const { return button->text(); }
inline QIcon QRollupCtrl::Page::icon() const { return button->icon(); }
inline QString QRollupCtrl::Page::toolTip() const { return button->toolTip(); }
//////////////////////////////////////////////////////////////////////////
QRollupCtrl::QRollupCtrl(QWidget* parent)
: QScrollArea(parent)
, m_layout(0)
{
m_body = new QWidget(this);
m_body->setBackgroundRole(QPalette::Button);
setWidgetResizable(true);
setAlignment(Qt::AlignLeft | Qt::AlignTop);
setWidget(m_body);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
relayout();
}
QRollupCtrl::~QRollupCtrl()
{
foreach(const QRollupCtrl::Page & c, m_pageList)
disconnect(c.widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
}
void QRollupCtrl::readSettings(const QString& qSettingsGroup)
{
QSettings settings;
settings.beginGroup(qSettingsGroup);
int i = 0;
foreach(const QRollupCtrl::Page & c, m_pageList) {
QString qObjectName = c.widget->objectName();
bool bHidden = settings.value(qObjectName, true).toBool();
setIndexVisible(i++, !bHidden);
}
settings.endGroup();
}
void QRollupCtrl::writeSettings(const QString& qSettingsGroup)
{
QSettings settings;
settings.beginGroup(qSettingsGroup);
for (int i = 0; i < count(); i++)
{
QString qObjectName;
bool bHidden = isPageHidden(i, qObjectName);
settings.setValue(qObjectName, bHidden);
}
}
void QRollupCtrl::updateTabs()
{
for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
{
QRollupCtrlButton* tB = (*i).button;
QWidget* tW = (*i).sv;
tB->setSelected(tW->isVisible());
tB->update();
}
}
int QRollupCtrl::insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text)
{
if (!widget)
{
return -1;
}
auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; });
if (it != m_pageList.cend())
{
return -1;
}
connect(widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
QRollupCtrl::Page c;
c.widget = widget;
c.button = new QRollupCtrlButton(m_body);
c.button->setContextMenuPolicy(Qt::CustomContextMenu);
connect(c.button, &QRollupCtrlButton::clicked, this, &QRollupCtrl::_q_buttonClicked);
connect(c.button, &QRollupCtrlButton::customContextMenuRequested, this, &QRollupCtrl::_q_custumButtonMenu);
c.sv = new QFrame(m_body);
c.sv->setObjectName("rollupPaneFrame");
// c.sv->setFixedHeight(qMax(widget->sizeHint().height(), widget->size().height()));
QVBoxLayout* layout = new QVBoxLayout;
layout->setMargin(3);
layout->addWidget(widget);
c.sv->setLayout(layout);
c.sv->setStyleSheet("QFrame#rollupPaneFrame {margin: 0px 2px 2px 2px; border: 1px solid #84807D; border-top:0px;}");
c.sv->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
c.sv->show();
c.setText(text);
c.setIcon(icon);
const int numPages = m_pageList.count();
if (index < 0 || index >= numPages)
{
m_pageList.append(c);
index = numPages - 1;
m_layout->insertWidget(m_layout->count() - 1, c.button);
m_layout->insertWidget(m_layout->count() - 1, c.sv);
}
else
{
m_pageList.insert(index, c);
relayout();
}
c.button->show();
updateTabs();
itemInserted(index);
return index;
}
void QRollupCtrl::_q_buttonClicked()
{
QObject* tb = sender();
QWidget* item = 0;
for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
{
if ((*i).button == tb)
{
item = (*i).widget;
break;
}
}
if (item)
{
setIndexVisible(indexOf(item), !item->isVisible());
}
}
int QRollupCtrl::count() const
{
return m_pageList.count();
}
bool QRollupCtrl::isPageHidden(int index, QString& qObjectName) const
{
if (index < 0 || index >= m_pageList.size())
{
return true;
}
const QRollupCtrl::Page& c = m_pageList.at(index);
qObjectName = c.widget->objectName();
return c.sv->isHidden();
}
void QRollupCtrl::setIndexVisible(int index, bool visible)
{
QRollupCtrl::Page* c = page(index);
if (!c)
{
return;
}
if (c->sv->isHidden() && visible)
{
c->sv->show();
}
else if (c->sv->isVisible() && !visible)
{
c->sv->hide();
}
updateTabs();
}
void QRollupCtrl::setWidgetVisible(QWidget* widget, bool visible)
{
setIndexVisible(indexOf(widget), visible);
}
void QRollupCtrl::relayout()
{
delete m_layout;
m_layout = new QVBoxLayout(m_body);
m_layout->setMargin(3);
m_layout->setSpacing(0);
for (QRollupCtrl::PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i)
{
m_layout->addWidget((*i).button);
m_layout->addWidget((*i).sv);
}
m_layout->addStretch();
updateTabs();
}
void QRollupCtrl::_q_widgetDestroyed(QObject* object)
{
// no verification - vtbl corrupted already
QWidget* p = (QWidget*)object;
QRollupCtrl::Page* c = page(p);
if (!p || !c)
{
return;
}
m_layout->removeWidget(c->sv);
m_layout->removeWidget(c->button);
c->sv->deleteLater(); // page might still be a child of sv
delete c->button;
m_pageList.removeOne(*c);
}
void QRollupCtrl::_q_custumButtonMenu([[maybe_unused]] const QPoint& pos)
{
QMenu menu;
menu.addAction("Expand All")->setData(-1);
menu.addAction("Collapse All")->setData(-2);
menu.addSeparator();
for (int i = 0; i < m_pageList.size(); ++i)
{
QRollupCtrl::Page* c = page(i);
QAction* action = menu.addAction(c->button->text());
action->setCheckable(true);
action->setChecked(c->sv->isVisible());
action->setData(i);
}
QAction* action = menu.exec(QCursor::pos());
if (!action)
{
return;
}
int res = action->data().toInt();
switch (res)
{
case -1: // fall through
case -2:
expandAllPages(res == -1);
break;
default:
{
QRollupCtrl::Page* c = page(res);
if (c)
{
setIndexVisible(res, !c->sv->isVisible());
}
}
break;
}
}
void QRollupCtrl::expandAllPages(bool v)
{
for (int i = 0; i < m_pageList.size(); i++)
{
setIndexVisible(i, v);
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void QRollupCtrl::clear()
{
while (!m_pageList.isEmpty())
{
removeItem(0);
}
}
void QRollupCtrl::removeItem(QWidget* widget)
{
auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; });
if (it != m_pageList.cend())
{
removeItem(it - m_pageList.cbegin());
}
}
void QRollupCtrl::removeItem(int index)
{
if (QWidget* w = widget(index))
{
disconnect(w, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed);
w->setParent(this);
// destroy internal data
_q_widgetDestroyed(w);
itemRemoved(index);
}
}
QWidget* QRollupCtrl::widget(int index) const
{
if (index < 0 || index >= (int) m_pageList.size())
{
return 0;
}
return m_pageList.at(index).widget;
}
int QRollupCtrl::indexOf(QWidget* widget) const
{
QRollupCtrl::Page* c = page(widget);
return c ? m_pageList.indexOf(*c) : -1;
}
void QRollupCtrl::setItemEnabled(int index, bool enabled)
{
QRollupCtrl::Page* c = page(index);
if (!c)
{
return;
}
c->button->setEnabled(enabled);
if (!enabled)
{
int curIndexUp = index;
int curIndexDown = curIndexUp;
const int count = m_pageList.count();
while (curIndexUp > 0 || curIndexDown < count - 1)
{
if (curIndexDown < count - 1)
{
if (page(++curIndexDown)->button->isEnabled())
{
index = curIndexDown;
break;
}
}
if (curIndexUp > 0)
{
if (page(--curIndexUp)->button->isEnabled())
{
index = curIndexUp;
break;
}
}
}
}
}
void QRollupCtrl::setItemText(int index, const QString& text)
{
QRollupCtrl::Page* c = page(index);
if (c)
{
c->setText(text);
}
}
void QRollupCtrl::setItemIcon(int index, const QIcon& icon)
{
QRollupCtrl::Page* c = page(index);
if (c)
{
c->setIcon(icon);
}
}
void QRollupCtrl::setItemToolTip(int index, const QString& toolTip)
{
QRollupCtrl::Page* c = page(index);
if (c)
{
c->setToolTip(toolTip);
}
}
bool QRollupCtrl::isItemEnabled(int index) const
{
const QRollupCtrl::Page* c = page(index);
return c && c->button->isEnabled();
}
QString QRollupCtrl::itemText(int index) const
{
const QRollupCtrl::Page* c = page(index);
return (c ? c->text() : QString());
}
QIcon QRollupCtrl::itemIcon(int index) const
{
const QRollupCtrl::Page* c = page(index);
return (c ? c->icon() : QIcon());
}
QString QRollupCtrl::itemToolTip(int index) const
{
const QRollupCtrl::Page* c = page(index);
return (c ? c->toolTip() : QString());
}
void QRollupCtrl::changeEvent(QEvent* ev)
{
if (ev->type() == QEvent::StyleChange)
{
updateTabs();
}
QFrame::changeEvent(ev);
}
void QRollupCtrl::showEvent(QShowEvent* ev)
{
if (isVisible())
{
updateTabs();
}
IEditor* pEditor = GetIEditor();
pEditor->SetEditMode(EEditMode::eEditModeSelect);
QFrame::showEvent(ev);
}
void QRollupCtrl::itemInserted(int index)
{
Q_UNUSED(index)
}
void QRollupCtrl::itemRemoved(int index)
{
Q_UNUSED(index)
}
#include <Controls/moc_QRollupCtrl.cpp>

@ -1,126 +0,0 @@
#ifndef CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H
#define CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#if !defined(Q_MOC_RUN)
#include <QFrame>
#include <QScrollArea>
#include <QIcon>
#endif
class QVBoxLayout;
class QRollupCtrlButton;
class QRollupCtrl
: public QScrollArea
{
Q_OBJECT
Q_PROPERTY(int count READ count)
public:
explicit QRollupCtrl(QWidget* parent = 0);
~QRollupCtrl();
int addItem(QWidget* widget, const QString& text);
int addItem(QWidget* widget, const QIcon& icon, const QString& text);
int insertItem(int index, QWidget* widget, const QString& text);
int insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text);
void clear();
void removeItem(QWidget* widget);
void removeItem(int index);
void setItemEnabled(int index, bool enabled);
bool isItemEnabled(int index) const;
void setItemText(int index, const QString& text);
QString itemText(int index) const;
void setItemIcon(int index, const QIcon& icon);
QIcon itemIcon(int index) const;
void setItemToolTip(int index, const QString& toolTip);
QString itemToolTip(int index) const;
QWidget* widget(int index) const;
int indexOf(QWidget* widget) const;
int count() const;
void readSettings (const QString& qSettingsGroup);
void writeSettings(const QString& qSettingsGroup);
public slots:
void setIndexVisible(int index, bool visible);
void setWidgetVisible(QWidget* widget, bool visible);
void expandAllPages(bool v);
protected:
virtual void itemInserted(int index);
virtual void itemRemoved(int index);
void changeEvent(QEvent*) override;
void showEvent(QShowEvent*) override;
private:
Q_DISABLE_COPY(QRollupCtrl)
struct Page
{
QRollupCtrlButton* button;
QFrame* sv;
QWidget* widget;
void setText(const QString& text);
void setIcon(const QIcon& is);
void setToolTip(const QString& tip);
QString text() const;
QIcon icon() const;
QString toolTip() const;
inline bool operator==(const Page& other) const
{
return widget == other.widget;
}
};
typedef QList<Page> PageList;
Page* page(QWidget* widget) const;
const Page* page(int index) const;
Page* page(int index);
void updateTabs();
void relayout();
bool isPageHidden(int index, QString& qObjectName) const;
QWidget* m_body;
PageList m_pageList;
QVBoxLayout* m_layout;
private slots:
void _q_buttonClicked();
void _q_widgetDestroyed(QObject*);
void _q_custumButtonMenu(const QPoint&);
};
//////////////////////////////////////////////////////////////////////////
inline int QRollupCtrl::addItem(QWidget* item, const QString& text)
{ return insertItem(-1, item, QIcon(), text); }
inline int QRollupCtrl::addItem(QWidget* item, const QIcon& iconSet, const QString& text)
{ return insertItem(-1, item, iconSet, text); }
inline int QRollupCtrl::insertItem(int index, QWidget* item, const QString& text)
{ return insertItem(index, item, QIcon(), text); }
#endif

@ -1,171 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : implementation file
#include "EditorDefs.h"
// Editor
#include "CryEditDoc.h"
#include "EditTool.h"
#include "ToolButton.h"
QEditorToolButton::QEditorToolButton(QWidget* parent /* = nullptr */)
: QPushButton(parent)
, m_styleSheet(styleSheet())
, m_toolClass(nullptr)
, m_toolCreated(nullptr)
, m_needDocument(true)
{
setSizePolicy({ QSizePolicy::Expanding, QSizePolicy::Fixed });
connect(this, &QAbstractButton::clicked, this, &QEditorToolButton::OnClicked);
GetIEditor()->RegisterNotifyListener(this);
}
QEditorToolButton::~QEditorToolButton()
{
GetIEditor()->UnregisterNotifyListener(this);
}
void QEditorToolButton::SetToolName(const QString& editToolName, const QString& userDataKey, void* userData)
{
IClassDesc* klass = GetIEditor()->GetClassFactory()->FindClass(editToolName.toUtf8().data());
if (!klass)
{
Warning(QStringLiteral("Editor Tool %1 not registered.").arg(editToolName).toUtf8().data());
return;
}
if (klass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL)
{
Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data());
return;
}
QScopedPointer<QObject> o(klass->CreateQObject());
if (!qobject_cast<CEditTool*>(o.data()))
{
Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data());
return;
}
SetToolClass(o->metaObject(), userDataKey, userData);
}
//////////////////////////////////////////////////////////////////////////
void QEditorToolButton::SetToolClass(const QMetaObject* toolClass, const QString& userDataKey, void* userData)
{
m_toolClass = toolClass;
m_userData = userData;
if (!userDataKey.isEmpty())
{
m_userDataKey = userDataKey;
}
}
void QEditorToolButton::OnEditorNotifyEvent(EEditorNotifyEvent event)
{
switch (event)
{
case eNotify_OnBeginNewScene:
case eNotify_OnBeginLoad:
case eNotify_OnBeginSceneOpen:
{
if (m_needDocument)
{
setEnabled(false);
}
break;
}
case eNotify_OnEndNewScene:
case eNotify_OnEndLoad:
case eNotify_OnEndSceneOpen:
{
if (m_needDocument)
{
setEnabled(true);
}
break;
}
case eNotify_OnEditToolChange:
{
CEditTool* tool = GetIEditor()->GetEditTool();
if (!tool || tool != m_toolCreated || tool->metaObject() != m_toolClass)
{
m_toolCreated = nullptr;
SetSelected(false);
}
}
default:
break;
}
}
void QEditorToolButton::OnClicked()
{
if (!m_toolClass)
{
return;
}
if (m_needDocument && !GetIEditor()->GetDocument()->IsDocumentReady())
{
return;
}
CEditTool* tool = GetIEditor()->GetEditTool();
if (tool && tool->IsMoveToObjectModeAfterEnd() && tool->metaObject() == m_toolClass && tool == m_toolCreated)
{
GetIEditor()->SetEditTool(nullptr);
SetSelected(false);
}
else
{
CEditTool* newTool = qobject_cast<CEditTool*>(m_toolClass->newInstance());
if (!newTool)
{
return;
}
m_toolCreated = newTool;
SetSelected(true);
if (m_userData)
{
newTool->SetUserData(m_userDataKey.toUtf8().data(), (void*)m_userData);
}
update();
// Must be last function, can delete this.
GetIEditor()->SetEditTool(newTool);
}
}
void QEditorToolButton::SetSelected(bool selected)
{
if (selected)
{
setStyleSheet(QStringLiteral("QPushButton { background-color: palette(highlight); color: palette(highlighted-text); }"));
}
else
{
setStyleSheet(m_styleSheet);
}
}
#include <Controls/moc_ToolButton.cpp>

@ -1,60 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H
#define CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H
#pragma once
// ToolButton.h : header file
//
#if !defined(Q_MOC_RUN)
#include <AzCore/PlatformDef.h>
#include <QPushButton>
#endif
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class SANDBOX_API QEditorToolButton
: public QPushButton
, public IEditorNotifyListener
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
Q_OBJECT
// Construction
public:
QEditorToolButton(QWidget* parent = nullptr);
virtual ~QEditorToolButton();
void SetToolClass(const QMetaObject* toolClass, const QString& userDataKey = 0, void* userData = nullptr);
void SetToolName(const QString& editToolName, const QString& userDataKey = 0, void* userData = nullptr);
// Set if this tool button relies on a loaded level / ready document. By default every tool button only works if a level is loaded.
// However some tools are also used without a loaded level (e.g. UI Emulator)
void SetNeedDocument(bool needDocument) { m_needDocument = needDocument; }
void SetSelected(bool selected);
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
protected:
void OnClicked();
const QString m_styleSheet;
//! Tool associated with this button.
const QMetaObject* m_toolClass;
CEditTool* m_toolCreated;
QString m_userDataKey;
void* m_userData;
bool m_needDocument;
};
#endif // CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H

@ -580,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);

@ -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<CObjectCloneTool*>(tool))
{
((CObjectCloneTool*)tool)->Accept();
}
CObjectCloneTool* cloneTool = new CObjectCloneTool;
GetIEditor()->SetEditTool(cloneTool);
GetIEditor()->SetModifiedFlag();
GetIEditor()->SetModifiedModule(eModifiedBrushes);
// Accept the clone operation if users didn't choose to stick duplicated entities to the cursor
// This setting can be changed in the global preference of the editor
if (!gSettings.deepSelectionSettings.bStickDuplicate)
{
cloneTool->Accept();
GetIEditor()->GetSelection()->FinishChanges();
}
}
}
void CCryEditApp::OnEditEscape()
{
if (!GetIEditor()->IsNewViewportInteractionModelEnabled())
{
CEditTool* pEditTool = GetIEditor()->GetEditTool();
// Abort current operation.
if (pEditTool)
{
// If Edit tool active cannot delete object.
CViewport* vp = GetIEditor()->GetActiveView();
if (GetIEditor()->GetEditTool()->OnKeyDown(vp, VK_ESCAPE, 0, 0))
{
return;
}
if (GetIEditor()->GetEditMode() == eEditModeSelectArea)
{
GetIEditor()->SetEditMode(eEditModeSelect);
}
// Disable current tool.
GetIEditor()->SetEditTool(0);
}
else
{
// Clear selection on escape.
GetIEditor()->ClearSelection();
}
}
}
void CCryEditApp::OnMoveObject()
{
////////////////////////////////////////////////////////////////////////
@ -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<CVertexSnappingModeTool*>(pEditTool) != nullptr);
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnObjectSetArea()
{
@ -3143,19 +3047,6 @@ void CCryEditApp::OnObjectSetHeight()
}
}
void CCryEditApp::OnObjectVertexSnapping()
{
CEditTool* pEditTool = GetIEditor()->GetEditTool();
if (qobject_cast<CVertexSnappingModeTool*>(pEditTool))
{
GetIEditor()->SetEditTool(NULL);
}
else
{
GetIEditor()->SetEditTool("EditTool.VertexSnappingMode");
}
}
void CCryEditApp::OnObjectmodifyFreeze()
{
// Freeze selection.
@ -3480,37 +3371,8 @@ void CCryEditApp::OnAlignToGrid()
}
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnAlignToVoxel()
{
CEditTool* pEditTool = GetIEditor()->GetEditTool();
if (qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr)
{
GetIEditor()->SetEditTool(nullptr);
}
else
{
GetIEditor()->SetEditTool(new CVoxelAligningTool());
}
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnUpdateAlignToVoxel(QAction* action)
{
Q_ASSERT(action->isCheckable());
CEditTool* pEditTool = GetIEditor()->GetEditTool();
action->setChecked(qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr);
action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty());
}
void CCryEditApp::OnShowHelpers()
{
CEditTool* pEditTool(GetIEditor()->GetEditTool());
if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce())
{
return;
}
GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
}
@ -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);

@ -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);

@ -279,7 +279,6 @@ void CCryEditDoc::DeleteContents()
// [LY-90904] move this to the EditorVegetationManager component
InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData);
GetIEditor()->SetEditTool(0); // Turn off any active edit tools.
GetIEditor()->SetEditMode(eEditModeSelect);
//////////////////////////////////////////////////////////////////////////

@ -1,123 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "ButtonsPanel.h"
// Qt
#include <QGridLayout>
// Editor
#include "Controls/ToolButton.h"
/////////////////////////////////////////////////////////////////////////////
// CButtonsPanel dialog
CButtonsPanel::CButtonsPanel(QWidget* parent)
: QWidget(parent)
{
}
CButtonsPanel::~CButtonsPanel()
{
}
//////////////////////////////////////////////////////////////////////////
void CButtonsPanel::AddButton(const SButtonInfo& button)
{
SButton b;
b.info = button;
m_buttons.push_back(b);
}
//////////////////////////////////////////////////////////////////////////
void CButtonsPanel::AddButton(const QString& name, const QString& toolClass)
{
SButtonInfo bi;
bi.name = name;
bi.toolClassName = toolClass;
AddButton(bi);
}
//////////////////////////////////////////////////////////////////////////
void CButtonsPanel::AddButton(const QString& name, const QMetaObject* pToolClass)
{
SButtonInfo bi;
bi.name = name;
bi.pToolClass = pToolClass;
AddButton(bi);
}
//////////////////////////////////////////////////////////////////////////
void CButtonsPanel::ClearButtons()
{
auto buttons = layout()->findChildren<QEditorToolButton*>();
foreach(auto button, buttons)
{
layout()->removeWidget(button);
delete button;
}
m_buttons.clear();
}
void CButtonsPanel::UncheckAll()
{
for (auto& button : m_buttons)
{
button.pButton->SetSelected(false);
}
}
void CButtonsPanel::OnInitDialog()
{
auto layout = new QGridLayout(this);
setLayout(layout);
layout->setMargin(4);
layout->setHorizontalSpacing(4);
layout->setVerticalSpacing(1);
// Create Buttons.
int index = 0;
for (auto& button : m_buttons)
{
button.pButton = new QEditorToolButton(this);
button.pButton->setObjectName(button.info.name);
button.pButton->setText(button.info.name);
button.pButton->SetNeedDocument(button.info.bNeedDocument);
button.pButton->setToolTip(button.info.toolTip);
if (button.info.pToolClass)
{
button.pButton->SetToolClass(button.info.pToolClass, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str());
}
else if (!button.info.toolClassName.isEmpty())
{
button.pButton->SetToolName(button.info.toolClassName, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str());
}
layout->addWidget(button.pButton, index / 2, index % 2);
connect(button.pButton, &QEditorToolButton::clicked, this, [&]() { OnButtonPressed(button.info); });
++index;
}
}
void CButtonsPanel::EnableButton(const QString& buttonName, bool enable)
{
for (auto& button : m_buttons)
{
if (button.pButton->objectName() == buttonName)
{
button.pButton->setEnabled(enable);
}
}
}
#include <Dialogs/moc_ButtonsPanel.cpp>

@ -1,76 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H
#define CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H
#pragma once
#if !defined(Q_MOC_RUN)
#include <QWidget>
#endif
class QEditorToolButton;
/////////////////////////////////////////////////////////////////////////////
// Panel with custom auto arranged buttons
class CButtonsPanel
: public QWidget
{
Q_OBJECT
public:
struct SButtonInfo
{
QString name;
QString toolClassName;
QString toolUserDataKey;
std::string toolUserData;
QString toolTip;
bool bNeedDocument;
const QMetaObject* pToolClass;
SButtonInfo()
: pToolClass(nullptr)
, bNeedDocument(true) {};
};
CButtonsPanel(QWidget* parent);
virtual ~CButtonsPanel();
virtual void AddButton(const SButtonInfo& button);
virtual void AddButton(const QString& name, const QString& toolClass);
virtual void AddButton(const QString& name, const QMetaObject* pToolClass);
virtual void EnableButton(const QString& buttonName, bool disable);
virtual void ClearButtons();
virtual void OnButtonPressed([[maybe_unused]] const SButtonInfo& button) {};
virtual void UncheckAll();
protected:
void ReleaseGuiButtons();
virtual void OnInitDialog();
//////////////////////////////////////////////////////////////////////////
struct SButton
{
SButtonInfo info;
QEditorToolButton* pButton;
SButton()
: pButton(nullptr) {};
};
std::vector<SButton> m_buttons;
};
#endif // CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H

File diff suppressed because it is too large Load Diff

@ -1,134 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Object edit mode describe viewport input behavior when operating on objects.
#ifndef CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H
#define CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H
#pragma once
// {87109FED-BDB5-4874-936D-338400079F58}
DEFINE_GUID(OBJECT_MODE_GUID, 0x87109fed, 0xbdb5, 0x4874, 0x93, 0x6d, 0x33, 0x84, 0x0, 0x7, 0x9f, 0x58);
#include "EditTool.h"
class CBaseObject;
class CDeepSelection;
/*!
* CObjectMode is an abstract base class for All Editing Tools supported by Editor.
* Edit tools handle specific editing modes in viewports.
*/
class SANDBOX_API CObjectMode
: public CEditTool
{
Q_OBJECT
public:
Q_INVOKABLE CObjectMode(QObject* parent = nullptr);
virtual ~CObjectMode();
static const GUID& GetClassID() { return OBJECT_MODE_GUID; }
// Registration function.
static void RegisterTool(CRegistrationContext& rc);
//////////////////////////////////////////////////////////////////////////
// CEditTool implementation.
//////////////////////////////////////////////////////////////////////////
virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {};
virtual void EndEditParams();
virtual void Display(struct DisplayContext& dc);
virtual void DisplaySelectionPreview(struct DisplayContext& dc);
virtual void DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject);
void DisplayExtraLightInfo(struct DisplayContext& dc);
virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags);
virtual bool OnKeyUp(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags);
virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; };
virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, QPoint& p0, QPoint& p1, const Vec3& value) override;
bool IsUpdateUIPanel() override { return true; }
protected:
enum ECommandMode
{
NothingMode = 0,
ScrollZoomMode,
SelectMode,
MoveMode,
RotateMode,
ScaleMode,
ScrollMode,
ZoomMode,
};
virtual bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnRButtonDown(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnRButtonUp(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnMButtonDown(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point);
virtual bool OnMouseLeave(CViewport* view);
void SetCommandMode(ECommandMode mode) { m_commandMode = mode; }
ECommandMode GetCommandMode() const { return m_commandMode; }
//! Ctrl-Click in move mode to move selected objects to given pos.
void MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point);
void SetObjectCursor(CViewport* view, CBaseObject* hitObj, bool bChangeNow = false);
virtual void DeleteThis() { delete this; };
void UpdateStatusText();
void AwakeObjectAtPoint(CViewport* view, const QPoint& point);
void HideMoveByFaceNormGizmo();
void HandleMoveByFaceNormal(HitContext& hitInfo);
void UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject);
protected:
bool m_openContext;
private:
void CheckDeepSelection(HitContext& hitContext, CViewport* view);
Vec3& GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale);
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
QPoint m_cMouseDownPos;
bool m_bDragThresholdExceeded;
ECommandMode m_commandMode;
GUID m_MouseOverObject;
typedef std::vector<GUID> TGuidContainer;
TGuidContainer m_PreviewGUIDs;
_smart_ptr<CDeepSelection> m_pDeepSelection;
bool m_bMoveByFaceNormManipShown;
CBaseObject* m_pHitObject;
bool m_bTransformChanged;
QPoint m_prevMousePos = QPoint(0, 0);
Vec3 m_lastValidMoveVector = Vec3(0, 0, 0);
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
#endif // CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H

@ -1,430 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#if defined(AZ_PLATFORM_WINDOWS)
#include <InitGuid.h>
#endif
#include "VertexSnappingModeTool.h"
// Editor
#include "Settings.h"
#include "Viewport.h"
#include "SurfaceInfoPicker.h"
#include "Material/Material.h"
#include "Util/KDTree.h"
// {3e008046-9269-41d7-82e2-07ffd7254c10}
DEFINE_GUID(VERTEXSNAPPING_MODE_GUID, 0x3e008046, 0x9269, 0x41d7, 0x82, 0xe2, 0x07, 0xff, 0xd7, 0x25, 0x4c, 0x10);
bool FindNearestVertex(CBaseObject* pObject, CKDTree* pTree, const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, Vec3& outPos, Vec3& vOutHitPosOnCube)
{
Matrix34 worldInvTM = pObject->GetWorldTM().GetInverted();
Vec3 vRaySrc = worldInvTM.TransformPoint(vWorldRaySrc);
Vec3 vRayDir = worldInvTM.TransformVector(vWorldRayDir);
Vec3 vLocalCameraPos = worldInvTM.TransformPoint(gEnv->pRenderer->GetCamera().GetPosition());
Vec3 vPos;
Vec3 vHitPosOnCube;
if (pTree)
{
if (pTree->FindNearestVertex(vRaySrc, vRayDir, gSettings.vertexSnappingSettings.vertexCubeSize, vLocalCameraPos, vPos, vHitPosOnCube))
{
outPos = pObject->GetWorldTM().TransformPoint(vPos);
vOutHitPosOnCube = pObject->GetWorldTM().TransformPoint(vHitPosOnCube);
return true;
}
}
else
{
// for objects without verts, the pivot is the nearest vertex
// return true if the ray hits the bounding box
outPos = pObject->GetWorldPos();
AABB bbox;
pObject->GetBoundBox(bbox);
if (bbox.IsContainPoint(vWorldRaySrc))
{
// if ray starts inside bounding box, reject cases where pivot is behind the ray
float hitDistAlongRay = vWorldRayDir.Dot(outPos - vWorldRaySrc);
if (hitDistAlongRay >= 0.f)
{
vHitPosOnCube = vWorldRaySrc + (vWorldRayDir * hitDistAlongRay);
return true;
}
}
else if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, bbox, vOutHitPosOnCube))
{
return true;
}
}
return false;
}
CVertexSnappingModeTool::CVertexSnappingModeTool()
{
m_modeStatus = eVSS_SelectFirstVertex;
m_bHit = false;
}
CVertexSnappingModeTool::~CVertexSnappingModeTool()
{
std::map<CBaseObjectPtr, CKDTree*>::iterator ii = m_ObjectKdTreeMap.begin();
for (; ii != m_ObjectKdTreeMap.end(); ++ii)
{
delete ii->second;
}
}
const GUID& CVertexSnappingModeTool::GetClassID()
{
return VERTEXSNAPPING_MODE_GUID;
}
void CVertexSnappingModeTool::RegisterTool(CRegistrationContext& rc)
{
rc.pClassFactory->RegisterClass(new CQtViewClass<CVertexSnappingModeTool>("EditTool.VertexSnappingMode", "Select", ESYSTEM_CLASS_EDITTOOL));
}
bool CVertexSnappingModeTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags)
{
CBaseObjectPtr pExcludedObject = NULL;
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex)
{
pExcludedObject = m_SelectionInfo.m_pObject;
}
m_bHit = HitTest(view, point, pExcludedObject, m_vHitVertex, m_pHitObject, m_Objects);
if (event == eMouseLDown && m_bHit && m_pHitObject && m_modeStatus == eVSS_SelectFirstVertex)
{
m_modeStatus = eVSS_MoveSelectVertexToAnotherVertex;
m_SelectionInfo.m_pObject = m_pHitObject;
m_SelectionInfo.m_vPos = m_vHitVertex;
GetIEditor()->BeginUndo();
m_pHitObject->StoreUndo("Vertex Snapping", true);
view->SetCapture();
}
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex)
{
if (event == eMouseLUp)
{
m_modeStatus = eVSS_SelectFirstVertex;
GetIEditor()->AcceptUndo("Vertex Snapping");
view->ReleaseMouse();
}
else if ((flags & MK_LBUTTON) && event == eMouseMove)
{
Vec3 vOffset = m_SelectionInfo.m_pObject->GetWorldPos() - m_SelectionInfo.m_vPos;
m_SelectionInfo.m_pObject->SetWorldPos(m_vHitVertex + vOffset);
m_SelectionInfo.m_vPos = m_SelectionInfo.m_pObject->GetWorldPos() - vOffset;
}
}
return true;
}
bool CVertexSnappingModeTool::HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects)
{
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
{
m_DebugBoxes.clear();
}
pOutHitObject = NULL;
outObjects.clear();
//
// Collect valid objects that mouse is over
//
CSurfaceInfoPicker picker;
CSurfaceInfoPicker::CExcludedObjects excludedObjects;
if (pExcludedObj)
{
excludedObjects.Add(pExcludedObj);
}
int nPickFlag = CSurfaceInfoPicker::ePOG_Entity;
std::vector<CBaseObjectPtr> penetratedObjects;
if (!picker.PickByAABB(point, nPickFlag, view, &excludedObjects, &penetratedObjects))
{
return false;
}
for (int i = 0, iCount(penetratedObjects.size()); i < iCount; ++i)
{
CMaterial* pMaterial = penetratedObjects[i]->GetMaterial();
if (pMaterial)
{
QString matName = pMaterial->GetName();
if (!QString::compare(matName, "Objects/sky/forest_sky_dome", Qt::CaseInsensitive))
{
continue;
}
}
outObjects.push_back(penetratedObjects[i]);
}
//
// Find the best vertex.
//
Vec3 vWorldRaySrc, vWorldRayDir;
view->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir);
std::vector<CBaseObjectPtr>::iterator ii = outObjects.begin();
float fNearestDist = 3e10f;
Vec3 vNearestPos;
CBaseObjectPtr pNearestObject = NULL;
for (ii = outObjects.begin(); ii != outObjects.end(); ++ii)
{
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
{
// add to debug boxes: the penetrated nodes of each object's kd-tree
if (auto pTree = GetKDTree(*ii))
{
Matrix34 invWorldTM = (*ii)->GetWorldTM().GetInverted();
int nIndex = m_DebugBoxes.size();
Vec3 vLocalRaySrc = invWorldTM.TransformPoint(vWorldRaySrc);
Vec3 vLocalRayDir = invWorldTM.TransformVector(vWorldRayDir);
pTree->GetPenetratedBoxes(vLocalRaySrc, vLocalRayDir, m_DebugBoxes);
for (int i = nIndex; i < m_DebugBoxes.size(); ++i)
{
m_DebugBoxes[i].SetTransformedAABB((*ii)->GetWorldTM(), m_DebugBoxes[i]);
}
}
}
// find the nearest vertex on this object
Vec3 vPos, vHitPosOnCube;
if (FindNearestVertex(*ii, GetKDTree(*ii), vWorldRaySrc, vWorldRayDir, vPos, vHitPosOnCube))
{
// is this the best so far?
float fDistance = vHitPosOnCube.GetDistance(vWorldRaySrc);
if (fDistance < fNearestDist)
{
fNearestDist = fDistance;
vNearestPos = vPos;
pNearestObject = *ii;
}
}
}
if (fNearestDist < 3e10f)
{
outHitPos = vNearestPos;
pOutHitObject = pNearestObject;
}
// if the mouse is over the object's pivot, use that instead of a vertex
if (pOutHitObject)
{
Vec3 vPivotPos = pOutHitObject->GetWorldPos();
Vec3 vPivotBox = GetCubeSize(view, pOutHitObject->GetWorldPos());
AABB pivotAABB(vPivotPos - vPivotBox, vPivotPos + vPivotBox);
Vec3 vPosOnPivotCube;
if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, pivotAABB, vPosOnPivotCube))
{
outHitPos = vPivotPos;
return true;
}
}
return pOutHitObject && pOutHitObject == pNearestObject;
}
Vec3 CVertexSnappingModeTool::GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const
{
if (!pView)
{
return Vec3(0, 0, 0);
}
float fScreenFactor = pView->GetScreenScaleFactor(pos);
return gSettings.vertexSnappingSettings.vertexCubeSize * Vec3(fScreenFactor, fScreenFactor, fScreenFactor);
}
void CVertexSnappingModeTool::Display(struct DisplayContext& dc)
{
const ColorB SnappedColor(0xFF00FF00);
const ColorB PivotColor(0xFF2020FF);
const ColorB VertexColor(0xFFFFAAAA);
// draw all objects under mouse
dc.SetColor(VertexColor);
for (int i = 0, iCount(m_Objects.size()); i < iCount; ++i)
{
AABB worldAABB;
m_Objects[i]->GetBoundBox(worldAABB);
if (!dc.view->IsBoundsVisible(worldAABB))
{
continue;
}
if (auto pStatObj = m_Objects[i]->GetIStatObj())
{
DrawVertexCubes(dc, m_Objects[i]->GetWorldTM(), pStatObj);
}
else
{
dc.DrawWireBox(worldAABB.min, worldAABB.max);
}
}
// draw object being moved
if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex && m_SelectionInfo.m_pObject)
{
dc.SetColor(QColor(0xaa, 0xaa, 0xaa));
if (auto pStatObj = m_SelectionInfo.m_pObject->GetIStatObj())
{
DrawVertexCubes(dc, m_SelectionInfo.m_pObject->GetWorldTM(), pStatObj);
}
else
{
AABB bounds;
m_SelectionInfo.m_pObject->GetBoundBox(bounds);
dc.DrawWireBox(bounds.min, bounds.max);
}
}
// draw pivot of hit object
if (m_pHitObject && (!m_bHit || m_bHit && !m_pHitObject->GetWorldPos().IsEquivalent(m_vHitVertex, 0.001f)))
{
dc.SetColor(PivotColor);
dc.DepthTestOff();
Vec3 vBoxSize = GetCubeSize(dc.view, m_pHitObject->GetWorldPos()) * 1.2f;
AABB vertexBox(m_pHitObject->GetWorldPos() - vBoxSize, m_pHitObject->GetWorldPos() + vBoxSize);
dc.DrawBall((vertexBox.min + vertexBox.max) * 0.5f, (vertexBox.max.x - vertexBox.min.x) * 0.5f);
dc.DepthTestOn();
}
// draw the vertex (or pivot) that's being hit
if (m_bHit)
{
dc.DepthTestOff();
dc.SetColor(SnappedColor);
Vec3 vBoxSize = GetCubeSize(dc.view, m_vHitVertex);
if (m_vHitVertex.IsEquivalent(m_pHitObject->GetWorldPos(), 0.001f))
{
dc.DrawBall(m_vHitVertex, vBoxSize.x * 1.2f);
}
else
{
dc.DrawSolidBox(m_vHitVertex - vBoxSize, m_vHitVertex + vBoxSize);
}
dc.DepthTestOn();
}
// draw wireframe of hit object
if (m_pHitObject && m_pHitObject->GetIStatObj())
{
SGeometryDebugDrawInfo dd;
dd.tm = m_pHitObject->GetWorldTM();
dd.color = ColorB(250, 0, 250, 30);
dd.lineColor = ColorB(255, 255, 0, 160);
dd.bExtrude = true;
m_pHitObject->GetIStatObj()->DebugDraw(dd);
}
// draw debug boxes
if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox)
{
ColorB boxColor(40, 40, 40);
for (int i = 0, iCount(m_DebugBoxes.size()); i < iCount; ++i)
{
dc.SetColor(boxColor);
boxColor += ColorB(25, 25, 25);
dc.DrawWireBox(m_DebugBoxes[i].min, m_DebugBoxes[i].max);
}
}
}
void CVertexSnappingModeTool::DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj)
{
if (!pStatObj)
{
return;
}
IIndexedMesh* pIndexedMesh = pStatObj->GetIndexedMesh();
if (pIndexedMesh)
{
IIndexedMesh::SMeshDescription md;
pIndexedMesh->GetMeshDescription(md);
for (int k = 0; k < md.m_nVertCount; ++k)
{
Vec3 vPos(0, 0, 0);
if (md.m_pVerts)
{
vPos = md.m_pVerts[k];
}
else if (md.m_pVertsF16)
{
vPos = md.m_pVertsF16[k].ToVec3();
}
else
{
continue;
}
vPos = tm.TransformPoint(vPos);
Vec3 vBoxSize = GetCubeSize(dc.view, vPos);
if (!m_bHit || !m_vHitVertex.IsEquivalent(vPos, 0.001f))
{
dc.DrawSolidBox(vPos - vBoxSize, vPos + vBoxSize);
}
}
}
for (int i = 0, iSubStatObjNum(pStatObj->GetSubObjectCount()); i < iSubStatObjNum; ++i)
{
IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(i);
if (pSubObj)
{
DrawVertexCubes(dc, tm * pSubObj->localTM, pSubObj->pStatObj);
}
}
}
CKDTree* CVertexSnappingModeTool::GetKDTree(CBaseObject* pObject)
{
auto existingTree = m_ObjectKdTreeMap.find(pObject);
if (existingTree != m_ObjectKdTreeMap.end())
{
return existingTree->second;
}
// Don't build a kd-tree for objects without verts
CKDTree* pTree = nullptr;
if (auto pStatObj = pObject->GetIStatObj())
{
pTree = new CKDTree();
pTree->Build(pObject->GetIStatObj());
}
m_ObjectKdTreeMap[pObject] = pTree;
return pTree;
}
#include <EditMode/moc_VertexSnappingModeTool.cpp>

@ -1,91 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H
#define CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H
#pragma once
#include "EditTool.h"
#include "Objects/BaseObject.h"
class CKDTree;
struct IDisplayViewport;
class CVertexSnappingModeTool
: public CEditTool
{
Q_OBJECT
public:
Q_INVOKABLE CVertexSnappingModeTool();
~CVertexSnappingModeTool();
static const GUID& GetClassID();
static void RegisterTool(CRegistrationContext& rc);
void Display(DisplayContext& dc);
bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
protected:
void DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj);
void DeleteThis(){ delete this; }
Vec3 GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const;
private:
using CEditTool::HitTest;
bool HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects);
CKDTree* GetKDTree(CBaseObject* pObject);
enum EVertexSnappingStatus
{
eVSS_SelectFirstVertex,
eVSS_MoveSelectVertexToAnotherVertex
};
EVertexSnappingStatus m_modeStatus;
struct SSelectionInfo
{
SSelectionInfo()
{
m_pObject = NULL;
m_vPos = Vec3(0, 0, 0);
}
CBaseObjectPtr m_pObject;
Vec3 m_vPos;
};
/// Info on object being moved (when in eVSS_MoveSelectVertexToAnotherVertex mode).
SSelectionInfo m_SelectionInfo;
/// Objects that mouse is over
std::vector<CBaseObjectPtr> m_Objects;
/// Position of vertex that mouse is hitting.
/// Invalid when m_bHit is false.
Vec3 m_vHitVertex;
/// Whether the mouse hit test succeeded
bool m_bHit;
/// Object that mouse is hitting
CBaseObjectPtr m_pHitObject;
/// Boxes to render for debug drawing
std::vector<AABB> m_DebugBoxes;
/// For each object, a tree containing its vertices.
std::map<CBaseObjectPtr, CKDTree*> m_ObjectKdTreeMap;
};
#endif // CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H

@ -1,89 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorDefs.h"
#include "EditTool.h"
// Editor
#include "Include/IObjectManager.h"
#include "Objects/SelectionGroup.h"
//////////////////////////////////////////////////////////////////////////
// Class description.
//////////////////////////////////////////////////////////////////////////
class CEditTool_ClassDesc
: public CRefCountClassDesc
{
virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; }
virtual REFGUID ClassID()
{
// {0A43AB8E-B1AE-44aa-93B1-229F73D58CA4}
static const GUID guid = {
0xa43ab8e, 0xb1ae, 0x44aa, { 0x93, 0xb1, 0x22, 0x9f, 0x73, 0xd5, 0x8c, 0xa4 }
};
return guid;
}
virtual QString ClassName() { return "EditTool.Default"; };
virtual QString Category() { return "EditTool"; };
};
CEditTool_ClassDesc g_stdClassDesc;
//////////////////////////////////////////////////////////////////////////
CEditTool::CEditTool(QObject* parent)
: QObject(parent)
{
m_pClassDesc = &g_stdClassDesc;
m_nRefCount = 0;
};
//////////////////////////////////////////////////////////////////////////
void CEditTool::SetParentTool(CEditTool* pTool)
{
m_pParentTool = pTool;
}
//////////////////////////////////////////////////////////////////////////
CEditTool* CEditTool::GetParentTool()
{
return m_pParentTool;
}
//////////////////////////////////////////////////////////////////////////
void CEditTool::Abort()
{
if (m_pParentTool)
{
GetIEditor()->SetEditTool(m_pParentTool);
}
else
{
GetIEditor()->SetEditTool(0);
}
}
//////////////////////////////////////////////////////////////////////////
void CEditTool::GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects)
{
CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
if (pSelection == NULL)
{
return;
}
for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
{
outAffectedObjects.push_back(pSelection->GetObject(i));
}
}
#include <moc_EditTool.cpp>

@ -1,175 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITOR_EDITTOOL_H
#define CRYINCLUDE_EDITOR_EDITTOOL_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "QtViewPaneManager.h"
#endif
class CViewport;
struct IClassDesc;
struct ITransformManipulator;
struct HitContext;
enum EEditToolType
{
EDIT_TOOL_TYPE_PRIMARY,
EDIT_TOOL_TYPE_SECONDARY,
};
/*!
* CEditTool is an abstract base class for All Editing Tools supported by Editor.
* Edit tools handle specific editing modes in viewports.
*/
class SANDBOX_API CEditTool
: public QObject
{
Q_OBJECT
public:
explicit CEditTool(QObject* parent = nullptr);
//////////////////////////////////////////////////////////////////////////
// For reference counting.
//////////////////////////////////////////////////////////////////////////
void AddRef() { m_nRefCount++; };
void Release()
{
AZ_Assert(m_nRefCount > 0, "Negative ref count");
if (--m_nRefCount == 0)
{
DeleteThis();
}
};
//! Returns class description for this tool.
IClassDesc* GetClassDesc() const { return m_pClassDesc; }
virtual void SetParentTool(CEditTool* pTool);
virtual CEditTool* GetParentTool();
virtual EEditToolType GetType() { return EDIT_TOOL_TYPE_PRIMARY; }
virtual EOperationMode GetMode() { return eOperationModeNone; }
// Abort tool.
virtual void Abort();
// Accept tool.
virtual void Accept([[maybe_unused]] bool resetPosition = false) {}
//! Status text displayed when this tool is active.
void SetStatusText(const QString& text) { m_statusText = text; };
QString GetStatusText() { return m_statusText; };
// Description:
// Activates tool.
// Arguments:
// pPreviousTool - Previously active edit tool.
// Return:
// True if the tool can be activated,
virtual bool Activate([[maybe_unused]] CEditTool* pPreviousTool) { return true; };
//! Used to pass user defined data to edit tool from ToolButton.
virtual void SetUserData([[maybe_unused]] const char* key, [[maybe_unused]] void* userData) {};
//! Called when user starts using this tool.
//! Flags is comnination of ObjectEditFlags flags.
virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {};
//! Called when user ends using this tool.
virtual void EndEditParams() {};
// Called each frame to display tool for given viewport.
virtual void Display(struct DisplayContext& dc) = 0;
//! Mouse callback sent from viewport.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Return false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport that sent this callback.
//! @param event Indicate what kind of event occured in viewport.
//! @param point 2D coordinate in viewport where event occured.
//! @param flags Additional flags (MK_LBUTTON,etc..) or from (MouseEventFlags) specified by viewport when calling callback.
virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) = 0;
//! Called when key in viewport is pressed while using this tool.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Returns false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport where key was pressed.
//! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h
//! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key.
//! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN)
virtual bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; };
//! Called when key in viewport is released while using this tool.
//! Returns true if event processed by callback, and all other processing for this event should abort.
//! Returns false if event was not processed by callback, and other processing for this event should occur.
//! @param view Viewport where key was pressed.
//! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h
//! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key.
//! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN)
virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; };
//! Called when mouse is moved and give oportunity to tool to set it own cursor.
//! @return true if cursor changed. or false otherwise.
virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; };
// Return objects affected by this edit tool. The returned objects usually will be the selected objects.
virtual void GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects);
// Called in response to the dragging of the manipulator in the view.
// Allow edit tool to handle manipulator dragging the way it wants.
virtual void OnManipulatorDrag([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] QPoint& p0, [[maybe_unused]] QPoint& p1, [[maybe_unused]] const Vec3& value) {}
virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, const Vec3& value)
{
// Overload with less boiler-plate
QPoint p0, p1;
OnManipulatorDrag(view, pManipulator, p0, p1, value);
}
// Called in response to mouse event of the manipulator in the view
virtual void OnManipulatorMouseEvent([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags, [[maybe_unused]] bool bHitGizmo = false) {}
virtual bool IsNeedMoveTool() { return false; }
virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return false; }
virtual bool IsNeedToSkipPivotBoxForObjects() { return false; }
virtual bool IsDisplayGrid() { return true; }
virtual bool IsUpdateUIPanel() { return false; }
virtual bool IsMoveToObjectModeAfterEnd() { return true; }
virtual bool IsCircleTypeRotateGizmo() { return false; }
// Draws object specific helpers for this tool
virtual void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) {}
// Hit test against edit tool
virtual bool HitTest([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] HitContext& hc) { return false; }
protected:
virtual ~CEditTool() {};
//////////////////////////////////////////////////////////////////////////
// Delete edit tool.
//////////////////////////////////////////////////////////////////////////
virtual void DeleteThis() = 0;
protected:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
_smart_ptr<CEditTool> m_pParentTool; // Pointer to parent edit tool.
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
QString m_statusText;
IClassDesc* m_pClassDesc;
int m_nRefCount;
};
#endif // CRYINCLUDE_EDITOR_EDITTOOL_H

@ -63,11 +63,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Field("DeepSelectionRange", &DeepSelection::m_deepSelectionRange)
->Field("StickDuplicate", &DeepSelection::m_stickDuplicate);
serialize.Class<VertexSnapping>()
->Version(1)
->Field("VertexCubeSize", &VertexSnapping::m_vertexCubeSize)
->Field("RenderPenetratedBoundBox", &VertexSnapping::m_bRenderPenetratedBoundBox);
serialize.Class<SliceSettings>()
->Version(1)
->Field("DynamicByDefault", &SliceSettings::m_slicesDynamicByDefault);
@ -78,7 +73,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Field("Messaging", &CEditorPreferencesPage_General::m_messaging)
->Field("Undo", &CEditorPreferencesPage_General::m_undo)
->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection)
->Field("Vertex Snapping", &CEditorPreferencesPage_General::m_vertexSnapping)
->Field("Slice Settings", &CEditorPreferencesPage_General::m_sliceSettings);
@ -119,12 +113,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Max, 1000.0f);
editContext->Class<VertexSnapping>("Vertex Snapping", "")
->DataElement(AZ::Edit::UIHandlers::SpinBox, &VertexSnapping::m_vertexCubeSize, "Vertex Cube Size", "Vertex Cube Size")
->Attribute(AZ::Edit::Attributes::Min, 0.0001f)
->Attribute(AZ::Edit::Attributes::Max, 1.0f)
->DataElement(AZ::Edit::UIHandlers::CheckBox, &VertexSnapping::m_bRenderPenetratedBoundBox, "Render Penetrated BoundBoxes", "Render Penetrated BoundBoxes");
editContext->Class<SliceSettings>("Slices", "")
->DataElement(AZ::Edit::UIHandlers::CheckBox, &SliceSettings::m_slicesDynamicByDefault, "New Slices Dynamic By Default", "When creating slices, they will be set to dynamic by default");
@ -135,7 +123,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_vertexSnapping, "Vertex Snapping", "Vertex Snapping")
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_sliceSettings, "Slices", "Slice Settings");
}
}
@ -189,10 +176,6 @@ void CEditorPreferencesPage_General::OnApply()
gSettings.deepSelectionSettings.fRange = m_deepSelection.m_deepSelectionRange;
gSettings.deepSelectionSettings.bStickDuplicate = m_deepSelection.m_stickDuplicate;
//vertex snapping
gSettings.vertexSnappingSettings.vertexCubeSize = m_vertexSnapping.m_vertexCubeSize;
gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox = m_vertexSnapping.m_bRenderPenetratedBoundBox;
//slices
gSettings.sliceSettings.dynamicByDefault = m_sliceSettings.m_slicesDynamicByDefault;
@ -236,10 +219,6 @@ void CEditorPreferencesPage_General::InitializeSettings()
m_deepSelection.m_deepSelectionRange = gSettings.deepSelectionSettings.fRange;
m_deepSelection.m_stickDuplicate = gSettings.deepSelectionSettings.bStickDuplicate;
//vertex snapping
m_vertexSnapping.m_vertexCubeSize = gSettings.vertexSnappingSettings.vertexCubeSize;
m_vertexSnapping.m_bRenderPenetratedBoundBox = gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox;
//slices
m_sliceSettings.m_slicesDynamicByDefault = gSettings.sliceSettings.dynamicByDefault;
}

@ -88,14 +88,6 @@ private:
bool m_stickDuplicate;
};
struct VertexSnapping
{
AZ_TYPE_INFO(VertexSnapping, "{20F16350-990C-4096-86E3-40D56DDDD702}")
float m_vertexCubeSize;
bool m_bRenderPenetratedBoundBox;
};
struct SliceSettings
{
AZ_TYPE_INFO(SliceSettings, "{8505CCC1-874C-4389-B51A-B9E5FF70CFDA}")
@ -107,7 +99,6 @@ private:
Messaging m_messaging;
Undo m_undo;
DeepSelection m_deepSelection;
VertexSnapping m_vertexSnapping;
SliceSettings m_sliceSettings;
QIcon m_icon;
};

@ -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"
@ -679,6 +678,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
}
SetCurrentCursor(STD_CURSOR_GAME);
}
if (m_renderViewport)
{
m_renderViewport->GetControllerList()->SetEnabled(false);
}
}
break;
@ -697,6 +701,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
RestoreViewportAfterGameMode();
}
if (m_renderViewport)
{
m_renderViewport->GetControllerList()->SetEnabled(true);
}
break;
case eNotify_OnCloseScene:
@ -727,6 +736,8 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
// meters above the terrain (default terrain height is 32)
viewTM.SetTranslation(Vec3(sx * 0.5f, sy * 0.5f, 34.0f));
SetViewTM(viewTM);
UpdateScene();
}
break;

@ -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)
{

@ -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;

@ -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<CRotateTool*>(m_pEditTool) != nullptr;
default:
return qobject_cast<CObjectMode*>(m_pEditTool) != nullptr && qobject_cast<CRotateTool*>(m_pEditTool) == nullptr;
}
}
CEditTool* CEditorImpl::CreateCorrectEditTool()
{
if (m_currEditMode == eEditModeRotate)
{
CBaseObject* selectedObj = nullptr;
CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection();
if (pSelection && pSelection->GetCount() > 0)
{
selectedObj = pSelection->GetObject(0);
}
return (new CRotateTool(selectedObj));
}
return (new CObjectMode);
}
void CEditorImpl::SetEditTool(CEditTool* tool, bool bStopCurrentTool)
{
CViewport* pViewport = GetIEditor()->GetActiveView();
if (pViewport)
{
pViewport->SetCurrentCursor(STD_CURSOR_DEFAULT);
}
if (!tool)
{
if (HasCorrectEditTool())
{
return;
}
else
{
tool = CreateCorrectEditTool();
}
}
if (!tool->Activate(m_pEditTool))
{
return;
}
if (bStopCurrentTool)
{
if (m_pEditTool && m_pEditTool != tool)
{
m_pEditTool->EndEditParams();
SetStatusText("Ready");
}
}
m_pEditTool = tool;
if (m_pEditTool)
{
m_pEditTool->BeginEditParams(this, 0);
}
Notify(eNotify_OnEditToolChange);
}
void CEditorImpl::ReinitializeEditTool()
{
if (m_pEditTool)
{
m_pEditTool->EndEditParams();
m_pEditTool->BeginEditParams(this, 0);
}
}
void CEditorImpl::SetEditTool(const QString& sEditToolName, [[maybe_unused]] bool bStopCurrentTool)
{
CEditTool* pTool = GetEditTool();
if (pTool && pTool->GetClassDesc())
{
// Check if already selected.
if (QString::compare(pTool->GetClassDesc()->ClassName(), sEditToolName, Qt::CaseInsensitive) == 0)
{
return;
}
}
IClassDesc* pClass = GetIEditor()->GetClassFactory()->FindClass(sEditToolName.toUtf8().data());
if (!pClass)
{
Warning("Editor Tool %s not registered.", sEditToolName.toUtf8().data());
return;
}
if (pClass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL)
{
Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data());
return;
}
QScopedPointer<QObject> o(pClass->CreateQObject());
if (CEditTool* pEditTool = qobject_cast<CEditTool*>(o.data()))
{
GetIEditor()->SetEditTool(pEditTool);
o.take();
return;
}
else
{
Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data());
return;
}
}
CEditTool* CEditorImpl::GetEditTool()
{
if (m_isNewViewportInteractionModelEnabled)
{
return nullptr;
}
return m_pEditTool;
}
ITransformManipulator* CEditorImpl::ShowTransformManipulator(bool bShow)
{
if (bShow)

@ -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<CEditTool> m_pEditTool;
CIconManager* m_pIconManager;
std::unique_ptr<SGizmoParameters> m_pGizmoParameters;
QString m_primaryCDFolder;

@ -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;

@ -25,7 +25,6 @@
#include "Objects/SelectionGroup.h"
#include "Include/IObjectManager.h"
#include "MathConversion.h"
#include "EditTool.h"
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_InfoBar.h>
@ -58,7 +57,6 @@ CInfoBar::CInfoBar(QWidget* parent)
m_prevEditMode = 0;
m_bSelectionLocked = false;
m_bSelectionChanged = false;
m_editTool = 0;
m_bDragMode = false;
m_prevMoveSpeed = 0;
m_currValue = Vec3(-111, +222, -333); //this wasn't initialized. I don't know what a good value is
@ -251,28 +249,6 @@ void CInfoBar::OnVectorUpdate(bool followTerrain)
ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator();
if (pManipulator)
{
CEditTool* pEditTool = GetIEditor()->GetEditTool();
if (pEditTool)
{
Vec3 diff = v - m_lastValue;
if (emode == eEditModeMove)
{
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
if (emode == eEditModeRotate)
{
diff = DEG2RAD(diff);
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
if (emode == eEditModeScale)
{
//GetIEditor()->RestoreUndo();
pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff);
}
}
return;
}
@ -421,39 +397,22 @@ void CInfoBar::IdleUpdate()
updateUI = true;
}
if (GetIEditor()->GetEditTool() != m_editTool)
{
updateUI = true;
m_editTool = GetIEditor()->GetEditTool();
}
QString str;
if (m_editTool)
if (updateUI)
{
str = m_editTool->GetStatusText();
if (str != m_sLastText)
if (m_numSelected == 0)
{
updateUI = true;
str = tr("None Selected");
}
}
if (updateUI)
{
if (!m_editTool)
else if (m_numSelected == 1)
{
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("1 Object Selected");
}
else
{
str = tr("%1 Objects Selected").arg(m_numSelected);
}
ui->m_statusText->setText(str);
m_sLastText = str;
}

@ -124,7 +124,6 @@ protected:
bool m_bDragMode;
QString m_sLastText;
CEditTool* m_editTool;
Vec3 m_lastValue;
Vec3 m_currValue;
float m_oldMainVolume;

@ -408,6 +408,13 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
}
}
UpdateCursorCapture(shouldCaptureCursor);
return shouldConsumeEvent;
}
void LegacyViewportCameraControllerInstance::UpdateCursorCapture(bool shouldCaptureCursor)
{
if (m_capturingCursor != shouldCaptureCursor)
{
if (shouldCaptureCursor)
@ -427,8 +434,14 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
m_capturingCursor = shouldCaptureCursor;
}
}
return shouldConsumeEvent;
void LegacyViewportCameraControllerInstance::ResetInputChannels()
{
m_modifiers = 0;
m_pressedKeys.clear();
UpdateCursorCapture(false);
m_inRotateMode = m_inMoveMode = m_inOrbitMode = m_inZoomMode = false;
}
void LegacyViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)

@ -35,6 +35,7 @@ namespace SandboxEditor
explicit LegacyViewportCameraControllerInstance(AzFramework::ViewportId viewport);
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void ResetInputChannels() override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
private:
@ -53,6 +54,7 @@ namespace SandboxEditor
bool HandleMouseMove(const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos);
bool HandleMouseWheel(float zDelta);
bool IsKeyDown(Qt::Key key) const;
void UpdateCursorCapture(bool shouldCaptureCursor);
bool m_inRotateMode = false;
bool m_inMoveMode = false;

@ -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 ));

@ -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<AZStd::string> 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"));
}
}
}

@ -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<IMaterial> 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<CMaterialPickTool>("EditTool.PickMaterial", "Material", ESYSTEM_CLASS_EDITTOOL));
}
//////////////////////////////////////////////////////////////////////////
void CMaterialPickTool::SetMaterial(_smart_ptr<IMaterial> 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 <Material/moc_MaterialPickTool.cpp>

@ -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<IMaterial> pMaterial);
virtual ~CMaterialPickTool();
// Delete itself.
void DeleteThis() { delete this; };
_smart_ptr<IMaterial> m_pMaterial;
QString m_displayString;
QPoint m_Mouse2DPosition;
SRayHitInfo m_HitInfo;
};
#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H

@ -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<NullEditTool>("EditTool.NullEditTool", "Select", ESYSTEM_CLASS_EDITTOOL));
}
#include <moc_NullEditTool.cpp>

@ -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; }
};

@ -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 <moc_ObjectCloneTool.cpp>

@ -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

@ -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);
}
}
}

@ -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;
}

@ -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<CObjectMode*>(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<AZ::Uuid>& /*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<size_t>(gizmoManager->GetGizmoCount());
@ -2757,9 +2677,6 @@ void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*compo
void CObjectManager::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
{
// return to default EditTool (in whatever transform mode is set)
GetIEditor()->SetEditTool(nullptr);
// show translate/rotate/scale gizmo again
if (IGizmoManager* gizmoManager = GetGizmoManager())
{

@ -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);

@ -17,7 +17,6 @@
#include "Include/IDisplayViewport.h"
#include "Include/HitContext.h"
#include "Util/Math.h"
#include "EditTool.h"
#include "IObjectManager.h"
#include <Cry_Geo.h>

@ -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;

@ -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

File diff suppressed because it is too large Load Diff

@ -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<Vec3> 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

@ -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
//////////////////////////////////////////////////////////////////////////

@ -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;

@ -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;
}

@ -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;
}
//////////////////////////////////////////////////////////////////////////

@ -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<CEditTool> m_pLocalEditTool;
std::vector<IRenderListener*> m_cRenderListeners;
typedef std::vector<_smart_ptr<IPostRenderer> > PostRenderers;

@ -202,6 +202,12 @@ bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFram
return interactionHandled;
}
void ViewportManipulatorControllerInstance::ResetInputChannels()
{
m_pendingDoubleClicks.clear();
m_state = AzToolsFramework::ViewportInteraction::MouseInteraction();
}
void ViewportManipulatorControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
m_curTime = event.m_time;

@ -26,6 +26,7 @@ namespace SandboxEditor
explicit ViewportManipulatorControllerInstance(AzFramework::ViewportId viewport);
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void ResetInputChannels() override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
private:

@ -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 <moc_VoxelAligningTool.cpp>

@ -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

@ -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

@ -21,7 +21,6 @@
#include <ISerialize.h>
#include <CryName.h>
#include <EditorDefs.h>
#include <EditTool.h>
#include <Resource.h>
/////////////////////////////////////////////////////////////////////////////

@ -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);
}
}
}

@ -24,6 +24,8 @@
#include <AzToolsFramework/ToolsComponents/EditorEntityIconComponentBus.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
#include <QtViewPane.h>
#include "../Editor/Objects/EntityObject.h"
#include <LmbrCentral/Rendering/MeshComponentBus.h>
#include <LmbrCentral/Rendering/RenderBoundsBus.h>

@ -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);

@ -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;

@ -28,6 +28,7 @@
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <QLabel>

@ -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

@ -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)

@ -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)

@ -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}
)

@ -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 <AzCore/base.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/PlatformIncl.h>
#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

@ -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 <tinyxml/tinyxml.h>
#include "Server/CrySimpleErrorLog.hpp"
#include "Server/CrySimpleJob.hpp"
#include <AzCore/base.h>
#include <AzCore/Debug/Trace.h>
#include <time.h>
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(&ltime);
tm today;
#if defined(AZ_PLATFORM_WINDOWS)
localtime_s(&today, &ltime);
#else
localtime_r(&ltime, &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);
}

@ -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 <string>
#include <set>
#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<std::string>& 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

@ -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
<ylo@cs.hut.fi> 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 <stdio.h>
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

@ -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 <AzCore/PlatformDef.h>
#include <assert.h>
#if defined(AZ_PLATFORM_MAC)
#include <netdb.h>
#include <unistd.h>
#elif defined(AZ_PLATFORM_WINDOWS)
#include <ws2tcpip.h>
#endif
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#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<sockaddr_in*>(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();
}

@ -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 <string>
#include <set>
#include <list>
#include <memory>
#include <AzCore/std/parallel/atomic.h>
class CSMTPMailer
{
public:
typedef std::string tstr;
typedef std::set<tstr> tstrcol;
typedef std::pair<std::string, std::string> tattachment;
typedef std::list<tattachment> 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<CCrySimpleSock> 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

@ -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 <AzCore/PlatformDef.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Debug/Trace.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Casting/lossy_cast.h>
#if defined(AZ_PLATFORM_WINDOWS)
#include <io.h>
#endif
#include "MD5.hpp"
#include <assert.h>
#include <zlib.h>
#include <algorithm>
#include <functional>
#include <iterator>
#include <cstdio>
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<uint8_t> Out;
std::vector<uint8_t> In(rSrc.c_str(), rSrc.c_str() + rSrc.size() + 1);
Replace(Out, In, rToReplace, rReplacement);
rRet = std::string(reinterpret_cast<char*>(&Out[0]));
}
void CSTLHelper::Replace(std::vector<uint8_t>& rRet, const std::vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& rOut)
{
std::vector<uint8_t> 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<uint8_t>& rIn)
{
std::vector<uint8_t> 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<uint8_t>& 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<uint32_t>(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<size_t>(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<size_t>(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<uint8_t>& rIn, std::vector<uint8_t>& 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<uint8_t>& rIn, std::vector<uint8_t>& 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;
}

@ -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 <vector>
#include <string>
typedef std::vector<std::string> tdEntryVec;
typedef std::pair<std::string, std::string> tdToken;
typedef std::vector<tdToken> tdTokenList;
typedef std::vector<uint8_t> tdDataVector;
//typedef std::vector<uint8_t> 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<uint8_t>& rRet, const std::vector<uint8_t>& 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<uint8_t>& rOut);
static bool FromFile(const std::string& rFileName, std::vector<uint8_t>& rIn);
static bool AppendToFile(const std::string& rFileName, const std::vector<uint8_t>& rOut);
static bool ToFileCompressed(const std::string& rFileName, const std::vector<uint8_t>& rOut);
static bool FromFileCompressed(const std::string& rFileName, std::vector<uint8_t>& rIn);
static bool Compress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut);
static bool Uncompress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut);
static void EndianSwizzleU64(uint64_t& S)
{
uint8_t* pT = reinterpret_cast<uint8_t*>(&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<uint8_t*>(&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<uint8_t*>(&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<const uint8_t*>(rStr.c_str()), rStr.size()); }
static tdHash Hash(const std::vector<uint8_t>& rData) { return Hash(&rData[0], rData.size()); }
static tdHash Hash(const std::vector<uint8_t>& 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

@ -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 <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/time.h>
#include <AzCore/std/algorithm.h>
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<const uint8_t*>(&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<tdHash*>(&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<uint32_t>(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);
}

@ -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 <Core/STLHelper.hpp>
#include <map>
#include <vector>
#include <list>
/*class CCrySimpleCacheEntry
{
tdCache
public:
protected:
private:
};*/
typedef std::map<tdHash, tdHash> tdEntries;
typedef std::map<tdHash, tdDataVector> 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<tdDataVector*> 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<tdDataVector*>& PendingCacheEntries(){return m_PendingCacheEntries; }
int Hit() const{return m_Hit; }
int Miss() const{return m_Miss; }
int EntryCount() const{return static_cast<int>(m_Entries.size()); }
};
#endif

@ -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 <Core/Common.h>
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Mailer.h>
#include <tinyxml/tinyxml.h>
#include <AzCore/std/time.h>
#include <AzCore/IO/SystemFile.h>
#include <string>
#include <map>
#include <algorithm>
#ifdef _MSC_VER
#include <process.h>
#include <direct.h>
#endif
#ifdef UNIX
#include <pthread.h>
#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<ICryError*> errors;
if (!dedupe)
{
for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it)
{
errors.push_back(*it);
}
}
else
{
std::map<tdHash, ICryError*> uniqErrors;
for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it)
{
ICryError* err = *it;
tdHash hash = err->Hash();
std::map<tdHash, ICryError*>::iterator uniq = uniqErrors.find(hash);
if (uniq != uniqErrors.end())
{
uniq->second->AddDuplicate(err);
delete err;
}
else
{
uniqErrors[hash] = err;
}
}
for (std::map<tdHash, ICryError*>::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<uint8_t> 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();
}
}
}

@ -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 <vector>
#include <list>
class ICryError;
typedef std::list<ICryError*> 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

@ -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 <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <tinyxml/tinyxml.h>
#include <AzCore/Jobs/Job.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/string/string.h>
#include <assert.h>
#include <memory>
//////////////////////////////////////////////////////////////////////////
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\
<html><title>shader compile server %s</title><body>"
#define TABLE_START "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH=640>\n\
<TR bgcolor=lightgrey><TH align=left>Description</TH><TH WIDTH=5></TH><TH>Value</TH><TH>Max</TH>\n\
<TH WIDTH=10>&nbsp;</TH><TH align=center>%</TH></TR>\n"
#define TABLE_INFO "<TR><TD>%s</TD><TD>&nbsp;</TD><TD align=left>%s</TD><TD align=center></TD><TD>&nbsp;</TD><TD valign=middle>\n\
</TD></TR>\n\
</TD></TR>\n"
#define TABLE_BAR "<TR><TD>%s</TD><TD>&nbsp;</TD><TD align=center>%d</TD><TD align=center>%d</TD><TD>&nbsp;</TD><TD valign=middle>\n\
<TABLE><TR><TD bgcolor=darkred style=\"width: %d;\" ></TD>\n\
<TD><FONT SIZE=1>%d%%</FONT></TD></TR>\n\
</TABLE></TD></TR>\n\
</TD></TR>\n"
#define TABLE_END "</TABLE>"
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("<b>Load</b>:", "");
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("<b>Setup</b>:", "");
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<int>(SEnviropment::Instance().m_FallbackTreshold));
Ret += CreateInfoText("DumpShaders", static_cast<int>(SEnviropment::Instance().m_DumpShaders));
Ret += CreateInfoText("<b>Cache</b>:", "");
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<int>(CCrySimpleCache::Instance().PendingCacheEntries().size()));
Ret += TABLE_END;
Ret += "</Body></hmtl>";
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<CHTTPRequest> 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();
}
}

@ -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 <AzCore/std/parallel/atomic.h>
#include <Core/Common.h>
#include <string>
extern bool g_Success;
class CCrySimpleSock;
class CCrySimpleHTTP
{
static AZStd::atomic_long ms_ExceptionCount;
CCrySimpleSock* m_pServerSocket;
void Init();
public:
CCrySimpleHTTP();
void Run();
};
#endif

@ -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 <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Common.h>
#include <Core/WindowsAPIImplementation.h>
#include <tinyxml/tinyxml.h>
#include <thread>
#include <sstream>
#include <fstream>
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
}

@ -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 <Core/Common.h>
#include <string>
#include <vector>
#include <string>
#include <AzCore/std/parallel/atomic.h>
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

@ -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 <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Common.h>
#include <tinyxml/tinyxml.h>
CCrySimpleJobCache::CCrySimpleJobCache(uint32_t requestIP)
: CCrySimpleJob(requestIP)
{
}
void CCrySimpleJobCache::CheckHashID(std::vector<uint8_t>& 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
}
}

@ -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 <Core/STLHelper.hpp>
class CCrySimpleJobCache
: public CCrySimpleJob
{
tdHash m_HashID;
protected:
void CheckHashID(std::vector<uint8_t>& rVec, size_t Size);
public:
CCrySimpleJobCache(uint32_t requestIP);
tdHash HashID() const{return m_HashID; }
};
#endif

@ -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 <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <tinyxml/tinyxml.h>
#include <Core/StdTypes.hpp>
#include <Core/WindowsAPIImplementation.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/sort.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/unordered_map.h>
#include <zlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#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<uint8_t>* 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<long>(m_GlobalCompileTasks);
}
}
CCrySimpleJobCompile::~CCrySimpleJobCompile()
{
--m_GlobalCompileTasks;
}
bool CCrySimpleJobCompile::Execute(const TiXmlElement* pElement)
{
std::vector<uint8_t>& 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<uint8_t> 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<uint8_t>& 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<AZStd::string, AZStd::string> 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<long>(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<uint8_t>(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<const unsigned char*>(permutation.c_str()), static_cast<unsigned int>(permutation.length()));
crcStringStream << crc;
const std::string HlslDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".hlsl";
CSTLHelper::ToFile(HlslDump, std::vector<uint8_t>(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<int, std::string>& f1, const std::pair<int, std::string>& 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<std::string> 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<int, std::string>(-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<int, std::string>(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<std::string> 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<std::string>& 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;
}

@ -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 <Core/Common.h>
#include <Core/Error.hpp>
class CCrySimpleJobCompile
: public CCrySimpleJobCache
{
public:
CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector<uint8_t>* 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<uint8_t>* m_pRVec;
virtual size_t SizeOf(std::vector<uint8_t>& rVec) = 0;
bool Compile(const TiXmlElement* pElement, std::vector<uint8_t>& 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<std::string>& 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<std::string> 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<int, std::string> > 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

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

Loading…
Cancel
Save