Merge branch 'development' of https://github.com/o3de/o3de into cgalvan/DraftStreamingImageAssetPixelAPI
commit
93261022f1
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bfc2ef8c6dbf2fba078e27e4e94384099e090468e679327dd826a5cbf22b04ed
|
||||
size 1019
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:708b12d41229afab78e0f7d59097ae3de855fea8525a920c5c214fc0ce79f1bd
|
||||
size 1209
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fab63af9b50790dca25330058e70517987ea8bf11c00f9353dd951ebdbd1dbe5
|
||||
size 5008
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include "AzAssetBrowserWindow.h"
|
||||
#include "AzAssetBrowser/ui_AssetBrowserWindow.h"
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/UI/AssetTreeView.h>
|
||||
#include <AzToolsFramework/AssetBrowser/UI/SortFilterProxyModel.hxx>
|
||||
#include <AzToolsFramework/AssetBrowser/UI/AssetBrowserModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetCache/AssetCacheBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserRequestBus.h>
|
||||
|
||||
const char* ASSET_BROWSER_PREVIEW_NAME = "Asset Browser (PREVIEW)";
|
||||
|
||||
AzAssetBrowserWindow::AzAssetBrowserWindow(const QString& name, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::AssetBrowserWindowClass())
|
||||
, m_assetDatabaseSortFilterProxyModel(new AssetBrowser::UI::SortFilterProxyModel(parent))
|
||||
, m_name(name)
|
||||
, m_assetBrowser(new AssetBrowser::UI::AssetTreeView(name, this))
|
||||
{
|
||||
EBUS_EVENT_RESULT(m_assetBrowserModel, AssetBrowser::AssetCache::AssetCacheRequestsBus, GetAssetBrowserModel);
|
||||
AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model");
|
||||
m_assetDatabaseSortFilterProxyModel->setSourceModel(m_assetBrowserModel);
|
||||
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->searchCriteriaWidget,
|
||||
&AzToolsFramework::SearchCriteriaWidget::SearchCriteriaChanged,
|
||||
m_assetDatabaseSortFilterProxyModel.data(),
|
||||
&AssetBrowser::UI::SortFilterProxyModel::OnSearchCriteriaChanged);
|
||||
|
||||
connect(m_assetBrowser, &QTreeView::customContextMenuRequested, this, &AzAssetBrowserWindow::OnContextMenu);
|
||||
}
|
||||
|
||||
AzAssetBrowserWindow::~AzAssetBrowserWindow()
|
||||
{
|
||||
m_assetBrowser->SaveState();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const AZ::Uuid& AzAssetBrowserWindow::GetClassID()
|
||||
{
|
||||
return AZ::AzTypeInfo<AzAssetBrowserWindow>::Uuid();
|
||||
}
|
||||
|
||||
void AzAssetBrowserWindow::OnContextMenu(const QPoint& point)
|
||||
{
|
||||
(void)point;
|
||||
//get the selected entries
|
||||
QModelIndexList sourceIndexes;
|
||||
for (const auto& index : m_assetBrowser->selectedIndexes())
|
||||
{
|
||||
sourceIndexes.push_back(m_assetDatabaseSortFilterProxyModel->mapToSource(index));
|
||||
}
|
||||
AZStd::vector<AssetBrowser::UI::Entry*> entries;
|
||||
m_assetBrowserModel->SourceIndexesToAssetDatabaseEntries(sourceIndexes, entries);
|
||||
|
||||
if (entries.empty() || entries.size() > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto entry = entries.front();
|
||||
|
||||
EBUS_EVENT(AssetBrowser::AssetBrowserRequestBus::Bus, OnItemContextMenu, this, entry);
|
||||
}
|
||||
|
||||
#include <AzAssetBrowser/moc_AzAssetBrowserWindow.cpp>
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AssetBrowserWindowClass;
|
||||
}
|
||||
|
||||
namespace AssetBrowser
|
||||
{
|
||||
namespace UI
|
||||
{
|
||||
class AssetTreeView;
|
||||
class SortFilterProxyModel;
|
||||
class AssetBrowserModel;
|
||||
}
|
||||
}
|
||||
|
||||
class AzAssetBrowserWindow
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AzAssetBrowserWindow, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(AzAssetBrowserWindow, "{20238D23-2670-44BC-9110-A51374C18B5A}");
|
||||
|
||||
explicit AzAssetBrowserWindow(const QString& name = "default", QWidget* parent = nullptr);
|
||||
virtual ~AzAssetBrowserWindow();
|
||||
|
||||
static const AZ::Uuid& GetClassID();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void OnContextMenu(const QPoint& point);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::AssetBrowserWindowClass> m_ui;
|
||||
QScopedPointer<AssetBrowser::UI::AssetBrowserModel> m_assetDatabaseModel;
|
||||
QScopedPointer<AssetBrowser::UI::SortFilterProxyModel> m_assetDatabaseSortFilterProxyModel;
|
||||
QString m_name;
|
||||
AssetBrowser::UI::AssetTreeView* m_assetBrowser;
|
||||
AssetBrowser::UI::AssetBrowserModel* m_assetBrowserModel;
|
||||
};
|
||||
|
||||
extern const char* ASSET_BROWSER_PREVIEW_NAME;
|
||||
@ -1,186 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "CVarMenu.h"
|
||||
|
||||
CVarMenu::CVarMenu(QWidget* parent)
|
||||
: QMenu(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void CVarMenu::AddCVarToggleItem(CVarToggle cVarToggle)
|
||||
{
|
||||
// Add CVar toggle action
|
||||
QAction* action = addAction(cVarToggle.m_displayName);
|
||||
connect(action, &QAction::triggered, [this, cVarToggle](bool checked)
|
||||
{
|
||||
// Update the CVar's value based on the action's new checked state
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(cVarToggle.m_cVarName.toUtf8().data());
|
||||
if (cVar)
|
||||
{
|
||||
SetCVar(cVar, checked ? cVarToggle.m_onValue : cVarToggle.m_offValue);
|
||||
}
|
||||
});
|
||||
action->setCheckable(true);
|
||||
|
||||
// Initialize the action's checked state based on the associated CVar's value
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(cVarToggle.m_cVarName.toUtf8().data());
|
||||
bool checked = (cVar && cVar->GetFVal() == cVarToggle.m_onValue);
|
||||
action->setChecked(checked);
|
||||
}
|
||||
|
||||
void CVarMenu::AddCVarValuesItem(QString cVarName,
|
||||
QString displayName,
|
||||
CVarDisplayNameValuePairs availableCVarValues,
|
||||
float offValue)
|
||||
{
|
||||
// Add a submenu offering multiple values for one CVar
|
||||
QMenu* menu = addMenu(displayName);
|
||||
QActionGroup* group = new QActionGroup(menu);
|
||||
group->setExclusive(true);
|
||||
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(cVarName.toUtf8().data());
|
||||
float cVarValue = cVar ? cVar->GetFVal() : 0.0f;
|
||||
for (const auto& availableCVarValue : availableCVarValues)
|
||||
{
|
||||
QAction* action = menu->addAction(availableCVarValue.first);
|
||||
action->setCheckable(true);
|
||||
group->addAction(action);
|
||||
|
||||
float availableOnValue = availableCVarValue.second;
|
||||
connect(action, &QAction::triggered, [this, action, cVarName, availableOnValue, offValue](bool checked)
|
||||
{
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(cVarName.toUtf8().data());
|
||||
if (cVar)
|
||||
{
|
||||
if (!checked)
|
||||
{
|
||||
SetCVar(cVar, offValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Toggle the CVar and update the action's checked state to
|
||||
// allow none of the items to be checked in the exclusive group.
|
||||
// Otherwise we could have just used the action's currently checked
|
||||
// state and updated the CVar's value only
|
||||
bool cVarOn = (cVar->GetFVal() == availableOnValue);
|
||||
checked = !cVarOn;
|
||||
SetCVar(cVar, checked ? availableOnValue : offValue);
|
||||
action->setChecked(checked);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize the action's checked state based on the CVar's current value
|
||||
bool checked = (cVarValue == availableOnValue);
|
||||
action->setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
void CVarMenu::AddUniqueCVarsItem(QString displayName,
|
||||
AZStd::vector<CVarToggle> availableCVars)
|
||||
{
|
||||
// Add a submenu of actions offering values for unique CVars
|
||||
QMenu* menu = addMenu(displayName);
|
||||
QActionGroup* group = new QActionGroup(menu);
|
||||
group->setExclusive(true);
|
||||
|
||||
for (const CVarToggle& availableCVar : availableCVars)
|
||||
{
|
||||
QAction* action = menu->addAction(availableCVar.m_displayName);
|
||||
action->setCheckable(true);
|
||||
group->addAction(action);
|
||||
|
||||
connect(action, &QAction::triggered, [this, action, availableCVar, availableCVars](bool checked)
|
||||
{
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(availableCVar.m_cVarName.toUtf8().data());
|
||||
if (cVar)
|
||||
{
|
||||
if (!checked)
|
||||
{
|
||||
SetCVar(cVar, availableCVar.m_offValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Toggle the CVar and update the action's checked state to
|
||||
// allow none of the items to be checked in the exclusive group.
|
||||
// Otherwise we could have just used the action's currently checked
|
||||
// state and updated the CVar's value only
|
||||
bool cVarOn = (cVar->GetFVal() == availableCVar.m_onValue);
|
||||
bool cVarChecked = !cVarOn;
|
||||
SetCVar(cVar, cVarChecked ? availableCVar.m_onValue : availableCVar.m_offValue);
|
||||
action->setChecked(cVarChecked);
|
||||
if (cVarChecked)
|
||||
{
|
||||
// Set the rest of the CVars in the group to their off values
|
||||
SetCVarsToOffValue(availableCVars, availableCVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize the action's checked state based on its associated CVar's current value
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(availableCVar.m_cVarName.toUtf8().data());
|
||||
bool cVarChecked = (cVar && cVar->GetFVal() == availableCVar.m_onValue);
|
||||
action->setChecked(cVarChecked);
|
||||
if (cVarChecked)
|
||||
{
|
||||
// Set the rest of the CVars in the group to their off values
|
||||
SetCVarsToOffValue(availableCVars, availableCVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVarMenu::AddResetCVarsItem()
|
||||
{
|
||||
QAction* action = addAction(tr("Reset to Default"));
|
||||
connect(action, &QAction::triggered, this, [this]()
|
||||
{
|
||||
for (auto it : m_originalCVarValues)
|
||||
{
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(it.first.c_str());
|
||||
if (cVar)
|
||||
{
|
||||
cVar->Set(it.second);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CVarMenu::SetCVarsToOffValue(const AZStd::vector<CVarToggle>& cVarToggles, const CVarToggle& excludeCVarToggle)
|
||||
{
|
||||
// Set all but the specified CVars to their off values
|
||||
for (const CVarToggle& cVarToggle : cVarToggles)
|
||||
{
|
||||
if (cVarToggle.m_cVarName != excludeCVarToggle.m_cVarName
|
||||
|| cVarToggle.m_onValue != excludeCVarToggle.m_onValue)
|
||||
{
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(cVarToggle.m_cVarName.toUtf8().data());
|
||||
if (cVar)
|
||||
{
|
||||
SetCVar(cVar, cVarToggle.m_offValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CVarMenu::SetCVar(ICVar* cVar, float newValue)
|
||||
{
|
||||
float oldValue = cVar->GetFVal();
|
||||
cVar->Set(newValue);
|
||||
|
||||
// Store original value for CVar if not already in the list
|
||||
m_originalCVarValues.emplace(AZStd::string(cVar->GetName()), oldValue);
|
||||
}
|
||||
|
||||
void CVarMenu::AddSeparator()
|
||||
{
|
||||
addSeparator();
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMenu>
|
||||
#include <QString>
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/utils.h>
|
||||
|
||||
struct ICVar;
|
||||
|
||||
class CVarMenu
|
||||
: public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// CVar that can be toggled on and off
|
||||
struct CVarToggle
|
||||
{
|
||||
QString m_cVarName;
|
||||
QString m_displayName;
|
||||
float m_onValue;
|
||||
float m_offValue;
|
||||
};
|
||||
|
||||
// List of a CVar's available values and their descriptions
|
||||
using CVarDisplayNameValuePairs = AZStd::vector<AZStd::pair<QString, float>>;
|
||||
|
||||
CVarMenu(QWidget* parent = nullptr);
|
||||
|
||||
// Add an action that turns a CVar on/off
|
||||
void AddCVarToggleItem(CVarToggle cVarToggle);
|
||||
|
||||
// Add a submenu of actions for a CVar that offers multiple values for exclusive selection
|
||||
void AddCVarValuesItem(QString cVarName,
|
||||
QString displayName,
|
||||
CVarDisplayNameValuePairs availableCVarValues,
|
||||
float offValue);
|
||||
|
||||
// Add a submenu of actions for exclusively turning unique CVars on/off
|
||||
void AddUniqueCVarsItem(QString displayName,
|
||||
AZStd::vector<CVarToggle> availableCVars);
|
||||
|
||||
// Add an action to reset all CVars to their original values before they
|
||||
// were modified by this menu
|
||||
void AddResetCVarsItem();
|
||||
|
||||
void AddSeparator();
|
||||
|
||||
private:
|
||||
void SetCVarsToOffValue(const AZStd::vector<CVarToggle>& cVarToggles, const CVarToggle& excludeCVarToggle);
|
||||
void SetCVar(ICVar* cVar, float newValue);
|
||||
|
||||
// Original CVar values before they were modified by this menu
|
||||
AZStd::unordered_map<AZStd::string, float> m_originalCVarValues;
|
||||
};
|
||||
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
class CommandManagerRequests : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
|
||||
struct CommandDetails
|
||||
{
|
||||
AZStd::string m_name;
|
||||
AZStd::vector<AZStd::string> m_arguments;
|
||||
};
|
||||
|
||||
virtual AZStd::vector<AZStd::string> GetCommands() const = 0;
|
||||
virtual void ExecuteCommand(const AZStd::string& commandLine) {}
|
||||
|
||||
virtual void GetCommandDetails(AZStd::string commandName, CommandDetails& outArguments) const = 0;
|
||||
|
||||
};
|
||||
|
||||
using CommandManagerRequestBus = AZ::EBus<CommandManagerRequests>;
|
||||
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ConfigGroup.h"
|
||||
|
||||
namespace Config
|
||||
{
|
||||
CConfigGroup::CConfigGroup()
|
||||
{
|
||||
}
|
||||
|
||||
CConfigGroup::~CConfigGroup()
|
||||
{
|
||||
for (IConfigVar* var : m_vars)
|
||||
{
|
||||
delete var;
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigGroup::AddVar(IConfigVar* var)
|
||||
{
|
||||
m_vars.push_back(var);
|
||||
}
|
||||
|
||||
AZ::u32 CConfigGroup::GetVarCount()
|
||||
{
|
||||
return aznumeric_cast<AZ::u32>(m_vars.size());
|
||||
}
|
||||
|
||||
IConfigVar* CConfigGroup::GetVar(const char* szName)
|
||||
{
|
||||
for (IConfigVar* var : m_vars)
|
||||
{
|
||||
if (0 == _stricmp(szName, var->GetName().c_str()))
|
||||
{
|
||||
return var;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const IConfigVar* CConfigGroup::GetVar(const char* szName) const
|
||||
{
|
||||
for (const IConfigVar* var : m_vars)
|
||||
{
|
||||
if (0 == _stricmp(szName, var->GetName().c_str()))
|
||||
{
|
||||
return var;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IConfigVar* CConfigGroup::GetVar(AZ::u32 index)
|
||||
{
|
||||
if (index < m_vars.size())
|
||||
{
|
||||
return m_vars[index];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const IConfigVar* CConfigGroup::GetVar(AZ::u32 index) const
|
||||
{
|
||||
if (index < m_vars.size())
|
||||
{
|
||||
return m_vars[index];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CConfigGroup::SaveToXML(XmlNodeRef node)
|
||||
{
|
||||
// save only values that don't have default values
|
||||
for (const IConfigVar* var : m_vars)
|
||||
{
|
||||
if (var->IsFlagSet(IConfigVar::eFlag_DoNotSave) || var->IsDefault())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* szName = var->GetName().c_str();
|
||||
|
||||
switch (var->GetType())
|
||||
{
|
||||
case IConfigVar::eType_BOOL:
|
||||
{
|
||||
bool currentValue = false;
|
||||
var->Get(¤tValue);
|
||||
node->setAttr(szName, currentValue);
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_INT:
|
||||
{
|
||||
int currentValue = 0;
|
||||
var->Get(¤tValue);
|
||||
node->setAttr(szName, currentValue);
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_FLOAT:
|
||||
{
|
||||
float currentValue = 0;
|
||||
var->Get(¤tValue);
|
||||
node->setAttr(szName, currentValue);
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_STRING:
|
||||
{
|
||||
AZStd::string currentValue;
|
||||
var->Get(¤tValue);
|
||||
node->setAttr(szName, currentValue.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigGroup::LoadFromXML(XmlNodeRef node)
|
||||
{
|
||||
// load values that are save-able
|
||||
for (IConfigVar* var : m_vars)
|
||||
{
|
||||
if (var->IsFlagSet(IConfigVar::eFlag_DoNotSave))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const char* szName = var->GetName().c_str();
|
||||
|
||||
switch (var->GetType())
|
||||
{
|
||||
case IConfigVar::eType_BOOL:
|
||||
{
|
||||
bool currentValue = false;
|
||||
var->GetDefault(¤tValue);
|
||||
if (node->getAttr(szName, currentValue))
|
||||
{
|
||||
var->Set(¤tValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_INT:
|
||||
{
|
||||
int currentValue = 0;
|
||||
var->GetDefault(¤tValue);
|
||||
if (node->getAttr(szName, currentValue))
|
||||
{
|
||||
var->Set(¤tValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_FLOAT:
|
||||
{
|
||||
float currentValue = 0;
|
||||
var->GetDefault(¤tValue);
|
||||
if (node->getAttr(szName, currentValue))
|
||||
{
|
||||
var->Set(¤tValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IConfigVar::eType_STRING:
|
||||
{
|
||||
AZStd::string currentValue;
|
||||
var->GetDefault(¤tValue);
|
||||
QString readValue(currentValue.c_str());
|
||||
if (node->getAttr(szName, readValue))
|
||||
{
|
||||
currentValue = readValue.toUtf8().data();
|
||||
var->Set(¤tValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
struct ICVar;
|
||||
class XmlNodeRef;
|
||||
|
||||
namespace Config
|
||||
{
|
||||
// Abstract configurable variable
|
||||
struct IConfigVar
|
||||
{
|
||||
public:
|
||||
enum EType
|
||||
{
|
||||
eType_BOOL,
|
||||
eType_INT,
|
||||
eType_FLOAT,
|
||||
eType_STRING,
|
||||
};
|
||||
|
||||
enum EFlags
|
||||
{
|
||||
eFlag_NoUI = 1 << 0,
|
||||
eFlag_NoCVar = 1 << 1,
|
||||
eFlag_DoNotSave = 1 << 2,
|
||||
};
|
||||
|
||||
IConfigVar(const char* szName, const char* szDescription, EType varType, AZ::u8 flags)
|
||||
: m_name(szName)
|
||||
, m_description(szDescription)
|
||||
, m_type(varType)
|
||||
, m_flags(flags)
|
||||
, m_ptr(nullptr)
|
||||
{};
|
||||
|
||||
virtual ~IConfigVar() = default;
|
||||
|
||||
AZ_FORCE_INLINE EType GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE const AZStd::string& GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE const AZStd::string& GetDescription() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE bool IsFlagSet(EFlags flag) const
|
||||
{
|
||||
return 0 != (m_flags & flag);
|
||||
}
|
||||
|
||||
virtual void Get(void* outPtr) const = 0;
|
||||
virtual void Set(const void* ptr) = 0;
|
||||
virtual bool IsDefault() const = 0;
|
||||
virtual void GetDefault(void* outPtr) const = 0;
|
||||
virtual void Reset() = 0;
|
||||
|
||||
static constexpr EType TranslateType(const bool&) { return eType_BOOL; }
|
||||
static constexpr EType TranslateType(const int&) { return eType_INT; }
|
||||
static constexpr EType TranslateType(const float&) { return eType_FLOAT; }
|
||||
static constexpr EType TranslateType(const AZStd::string&) { return eType_STRING; }
|
||||
|
||||
protected:
|
||||
EType m_type;
|
||||
AZ::u8 m_flags;
|
||||
AZStd::string m_name;
|
||||
AZStd::string m_description;
|
||||
void* m_ptr;
|
||||
ICVar* m_pCVar;
|
||||
};
|
||||
|
||||
// Group of configuration variables with optional mapping to CVars
|
||||
class CConfigGroup
|
||||
{
|
||||
private:
|
||||
using TConfigVariables = AZStd::vector<IConfigVar*> ;
|
||||
TConfigVariables m_vars;
|
||||
|
||||
using TConsoleVariables = AZStd::vector<ICVar*>;
|
||||
TConsoleVariables m_consoleVars;
|
||||
|
||||
public:
|
||||
CConfigGroup();
|
||||
virtual ~CConfigGroup();
|
||||
|
||||
void AddVar(IConfigVar* var);
|
||||
AZ::u32 GetVarCount();
|
||||
IConfigVar* GetVar(const char* szName);
|
||||
IConfigVar* GetVar(AZ::u32 index);
|
||||
const IConfigVar* GetVar(const char* szName) const;
|
||||
const IConfigVar* GetVar(AZ::u32 index) const;
|
||||
|
||||
void SaveToXML(XmlNodeRef node);
|
||||
void LoadFromXML(XmlNodeRef node);
|
||||
};
|
||||
};
|
||||
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyAnimationCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
|
||||
// Editor
|
||||
#include "Util/UIEnumerations.h"
|
||||
#include "IResourceSelectorHost.h"
|
||||
|
||||
AnimationPropertyCtrl::AnimationPropertyCtrl(QWidget *pParent)
|
||||
: QWidget(pParent)
|
||||
{
|
||||
m_animationLabel = new QLabel;
|
||||
|
||||
m_pApplyButton = new QToolButton;
|
||||
m_pApplyButton->setIcon(QIcon(":/reflectedPropertyCtrl/img/apply.png"));
|
||||
|
||||
m_pApplyButton->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
QHBoxLayout *pLayout = new QHBoxLayout(this);
|
||||
pLayout->setContentsMargins(0, 0, 0, 0);
|
||||
pLayout->addWidget(m_animationLabel, 1);
|
||||
pLayout->addWidget(m_pApplyButton);
|
||||
|
||||
connect(m_pApplyButton, &QAbstractButton::clicked, this, &AnimationPropertyCtrl::OnApplyClicked);
|
||||
};
|
||||
|
||||
AnimationPropertyCtrl::~AnimationPropertyCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void AnimationPropertyCtrl::SetValue(const CReflectedVarAnimation &animation)
|
||||
{
|
||||
m_animation = animation;
|
||||
m_animationLabel->setText(animation.m_animation.c_str());
|
||||
}
|
||||
|
||||
CReflectedVarAnimation AnimationPropertyCtrl::value() const
|
||||
{
|
||||
return m_animation;
|
||||
}
|
||||
|
||||
void AnimationPropertyCtrl::OnApplyClicked()
|
||||
{
|
||||
QStringList cSelectedAnimations;
|
||||
int nTotalAnimations(0);
|
||||
int nCurrentAnimation(0);
|
||||
|
||||
QString combinedString = GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("animation");
|
||||
SplitString(combinedString, cSelectedAnimations, ',');
|
||||
|
||||
nTotalAnimations = cSelectedAnimations.size();
|
||||
for (nCurrentAnimation = 0; nCurrentAnimation < nTotalAnimations; ++nCurrentAnimation)
|
||||
{
|
||||
QString& rstrCurrentAnimAction = cSelectedAnimations[nCurrentAnimation];
|
||||
if (!rstrCurrentAnimAction.isEmpty())
|
||||
{
|
||||
m_animation.m_animation = rstrCurrentAnimAction.toUtf8().data();
|
||||
m_animationLabel->setText(m_animation.m_animation.c_str());
|
||||
emit ValueChanged(m_animation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* AnimationPropertyCtrl::GetFirstInTabOrder()
|
||||
{
|
||||
return m_pApplyButton;
|
||||
}
|
||||
QWidget* AnimationPropertyCtrl::GetLastInTabOrder()
|
||||
{
|
||||
return m_pApplyButton;
|
||||
}
|
||||
|
||||
void AnimationPropertyCtrl::UpdateTabOrder()
|
||||
{
|
||||
setTabOrder(m_pApplyButton, m_pApplyButton);
|
||||
}
|
||||
|
||||
|
||||
QWidget* AnimationPropertyWidgetHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
AnimationPropertyCtrl* newCtrl = aznew AnimationPropertyCtrl(pParent);
|
||||
connect(newCtrl, &AnimationPropertyCtrl::ValueChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
|
||||
void AnimationPropertyWidgetHandler::ConsumeAttribute(AnimationPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
Q_UNUSED(GUI);
|
||||
Q_UNUSED(attrib);
|
||||
Q_UNUSED(attrValue);
|
||||
Q_UNUSED(debugName);
|
||||
}
|
||||
|
||||
void AnimationPropertyWidgetHandler::WriteGUIValuesIntoProperty(size_t index, AnimationPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarAnimation val = GUI->value();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
|
||||
bool AnimationPropertyWidgetHandler::ReadValuesIntoGUI(size_t index, AnimationPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarAnimation val = instance;
|
||||
GUI->SetValue(val);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyAnimationCtrl.cpp>
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#endif
|
||||
|
||||
class QToolButton;
|
||||
class QLabel;
|
||||
class QHBoxLayout;
|
||||
|
||||
class AnimationPropertyCtrl
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnimationPropertyCtrl, AZ::SystemAllocator, 0);
|
||||
|
||||
AnimationPropertyCtrl(QWidget* pParent = nullptr);
|
||||
virtual ~AnimationPropertyCtrl();
|
||||
|
||||
CReflectedVarAnimation value() const;
|
||||
|
||||
QWidget* GetFirstInTabOrder();
|
||||
QWidget* GetLastInTabOrder();
|
||||
void UpdateTabOrder();
|
||||
|
||||
signals:
|
||||
void ValueChanged(CReflectedVarAnimation value);
|
||||
|
||||
public slots:
|
||||
void SetValue(const CReflectedVarAnimation& animation);
|
||||
|
||||
protected slots:
|
||||
void OnApplyClicked();
|
||||
|
||||
private:
|
||||
QToolButton* m_pApplyButton;
|
||||
QLabel* m_animationLabel;
|
||||
|
||||
CReflectedVarAnimation m_animation;
|
||||
};
|
||||
|
||||
class AnimationPropertyWidgetHandler
|
||||
: QObject
|
||||
, public AzToolsFramework::PropertyHandler < CReflectedVarAnimation, AnimationPropertyCtrl >
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnimationPropertyWidgetHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Animation", 0x8d5284dc); }
|
||||
virtual bool IsDefaultHandler() const override { return true; }
|
||||
virtual QWidget* GetFirstInTabOrder(AnimationPropertyCtrl* widget) override { return widget->GetFirstInTabOrder(); }
|
||||
virtual QWidget* GetLastInTabOrder(AnimationPropertyCtrl* widget) override { return widget->GetLastInTabOrder(); }
|
||||
virtual void UpdateWidgetInternalTabbing(AnimationPropertyCtrl* widget) override { widget->UpdateTabOrder(); }
|
||||
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override;
|
||||
virtual void ConsumeAttribute(AnimationPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, AnimationPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
virtual bool ReadValuesIntoGUI(size_t index, AnimationPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
//! Allows handlers to be notified when settings are changed to refresh accordingly
|
||||
class EditorPreferencesNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
//! Notifies about changes in the Editor Preferences
|
||||
virtual void OnEditorPreferencesChanged() {}
|
||||
};
|
||||
using EditorPreferencesNotificationBus = AZ::EBus<EditorPreferencesNotifications>;
|
||||
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_IOBSERVABLE_H
|
||||
#define CRYINCLUDE_EDITOR_IOBSERVABLE_H
|
||||
#pragma once
|
||||
|
||||
//! Observable macro to be used in pure interfaces
|
||||
#define DEFINE_OBSERVABLE_PURE_METHODS(observerClassName) \
|
||||
virtual bool RegisterObserver(observerClassName * pObserver) = 0; \
|
||||
virtual bool UnregisterObserver(observerClassName * pObserver) = 0; \
|
||||
virtual void UnregisterAllObservers() = 0;
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_IOBSERVABLE_H
|
||||
@ -1,2 +0,0 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "..\\res\\lyeditor.ico"
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#define IDI_ICON1 2
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "SubObjSelection.h"
|
||||
|
||||
SSubObjSelOptions g_SubObjSelOptions;
|
||||
|
||||
/*
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSubObjSelContext::IsEmpty() const
|
||||
{
|
||||
if (GetCount() == 0)
|
||||
return false;
|
||||
for (int i = 0; i < GetCount(); i++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(i);
|
||||
if (!pSel->IsEmpty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSubObjSelContext::ModifySelection( SSubObjSelectionModifyContext &modCtx )
|
||||
{
|
||||
for (int n = 0; n < GetCount(); n++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(n);
|
||||
if (pSel->IsEmpty())
|
||||
continue;
|
||||
modCtx.pSubObjSelection = pSel;
|
||||
pSel->pGeometry->SubObjSelectionModify( modCtx );
|
||||
}
|
||||
if (modCtx.type == SO_MODIFY_MOVE)
|
||||
{
|
||||
OnSelectionChange();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSubObjSelContext::AcceptModifySelection()
|
||||
{
|
||||
for (int n = 0; n < GetCount(); n++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(n);
|
||||
if (pSel->IsEmpty())
|
||||
continue;
|
||||
if (pSel->pGeometry)
|
||||
pSel->pGeometry->Update();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sub Object element type.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjElementType
|
||||
{
|
||||
SO_ELEM_NONE = 0,
|
||||
SO_ELEM_VERTEX,
|
||||
SO_ELEM_EDGE,
|
||||
SO_ELEM_FACE,
|
||||
SO_ELEM_POLYGON,
|
||||
SO_ELEM_UV,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjDisplayType
|
||||
{
|
||||
SO_DISPLAY_WIREFRAME,
|
||||
SO_DISPLAY_FLAT,
|
||||
SO_DISPLAY_GEOMETRY,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Options for sub-object selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SSubObjSelOptions
|
||||
{
|
||||
bool bSelectByVertex;
|
||||
bool bIgnoreBackfacing;
|
||||
int nMatID;
|
||||
|
||||
bool bSoftSelection;
|
||||
float fSoftSelFalloff;
|
||||
|
||||
// Display options.
|
||||
bool bDisplayBackfacing;
|
||||
bool bDisplayNormals;
|
||||
float fNormalsLength;
|
||||
ESubObjDisplayType displayType;
|
||||
|
||||
SSubObjSelOptions()
|
||||
{
|
||||
bSelectByVertex = false;
|
||||
bIgnoreBackfacing = false;
|
||||
bSoftSelection = false;
|
||||
nMatID = 0;
|
||||
fSoftSelFalloff = 1;
|
||||
|
||||
bDisplayBackfacing = true;
|
||||
bDisplayNormals = false;
|
||||
displayType = SO_DISPLAY_FLAT;
|
||||
fNormalsLength = 0.4f;
|
||||
}
|
||||
};
|
||||
|
||||
extern SSubObjSelOptions g_SubObjSelOptions;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjSelectionModifyType
|
||||
{
|
||||
SO_MODIFY_UNSELECT,
|
||||
SO_MODIFY_MOVE,
|
||||
SO_MODIFY_ROTATE,
|
||||
SO_MODIFY_SCALE,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// This structure is passed when user is dragging sub object selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SSubObjSelectionModifyContext
|
||||
{
|
||||
CViewport* view;
|
||||
ESubObjSelectionModifyType type;
|
||||
Vec3 vValue;
|
||||
Matrix34 worldRefFrame;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Manifest>
|
||||
</Manifest>
|
||||
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CategoriesList.h"
|
||||
|
||||
ComponentCategoryList::ComponentCategoryList(QWidget* parent /*= nullptr*/)
|
||||
: QTreeWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ComponentCategoryList::Init()
|
||||
{
|
||||
setColumnCount(1);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setDragDropMode(QAbstractItemView::DragDropMode::DragOnly);
|
||||
setDragEnabled(true);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setAllColumnsShowFocus(true);
|
||||
setStyleSheet("QTreeWidget { selection-background-color: rgba(255,255,255,0.2); }");
|
||||
|
||||
QStringList headers;
|
||||
headers << tr("Categories");
|
||||
setHeaderLabels(headers);
|
||||
|
||||
const QString parentCategoryIconPath = QString("Icons/PropertyEditor/Browse_on.png");
|
||||
const QString categoryIconPath = QString("Icons/PropertyEditor/Browse.png");
|
||||
|
||||
QTreeWidgetItem* allCategory = new QTreeWidgetItem(this);
|
||||
allCategory->setText(0, "All");
|
||||
allCategory->setIcon(0, QIcon(categoryIconPath));
|
||||
|
||||
// Need this briefly to collect the list of available categories.
|
||||
ComponentDataModel dataModel(this);
|
||||
for (const auto& cat : dataModel.GetCategories())
|
||||
{
|
||||
QString categoryString = QString(cat.c_str());
|
||||
QStringList categories = categoryString.split('/', Qt::SkipEmptyParts);
|
||||
|
||||
QTreeWidgetItem* parent = nullptr;
|
||||
QTreeWidgetItem* categoryWidget = nullptr;
|
||||
|
||||
for (const auto& categoryName : categories)
|
||||
{
|
||||
if (parent)
|
||||
{
|
||||
categoryWidget = new QTreeWidgetItem(parent);
|
||||
categoryWidget->setIcon(0, QIcon(categoryIconPath));
|
||||
|
||||
// Store the full category path in a user role because we'll need it to locate the actual category
|
||||
categoryWidget->setData(0, Qt::UserRole, QVariant::fromValue(categoryString));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto existingCategory = findItems(categoryName, Qt::MatchExactly);
|
||||
if (existingCategory.empty())
|
||||
{
|
||||
categoryWidget = new QTreeWidgetItem(this);
|
||||
categoryWidget->setIcon(0, QIcon(parentCategoryIconPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryWidget = static_cast<QTreeWidgetItem*>(existingCategory.first());
|
||||
categoryWidget->setIcon(0, QIcon(parentCategoryIconPath));
|
||||
}
|
||||
}
|
||||
|
||||
parent = categoryWidget;
|
||||
|
||||
categoryWidget->setText(0, categoryName);
|
||||
}
|
||||
}
|
||||
|
||||
expandAll();
|
||||
|
||||
connect(this, &QTreeWidget::itemClicked, this, &ComponentCategoryList::OnItemClicked);
|
||||
}
|
||||
|
||||
void ComponentCategoryList::OnItemClicked(QTreeWidgetItem* item, int /*column*/)
|
||||
{
|
||||
QVariant userData = item->data(0, Qt::UserRole);
|
||||
if (userData.isValid())
|
||||
{
|
||||
// Send in the full category path, not just the child category name
|
||||
emit OnCategoryChange(userData.value<QString>().toStdString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
emit OnCategoryChange(item->text(0).toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#include <UI/ComponentPalette/moc_CategoriesList.cpp>
|
||||
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ComponentDataModel.h"
|
||||
#include <QTreeWidget>
|
||||
#endif
|
||||
|
||||
//! ComponentCategoryList
|
||||
//! Provides a list of all reflected categories that users can select for quick
|
||||
//! filtering the filtered component list.
|
||||
class ComponentCategoryList : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(ComponentCategoryList, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit ComponentCategoryList(QWidget* parent = nullptr);
|
||||
|
||||
void Init();
|
||||
|
||||
Q_SIGNALS:
|
||||
void OnCategoryChange(const char* category);
|
||||
|
||||
protected:
|
||||
|
||||
// Will emit OnCategoryChange signal
|
||||
void OnItemClicked(QTreeWidgetItem* item, int column);
|
||||
|
||||
};
|
||||
@ -1,547 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ComponentDataModel.h"
|
||||
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Commands/EntityStateCommand.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/API/EntityCompositionRequestBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
|
||||
#include <Editor/IEditor.h>
|
||||
#include <Editor/Viewport.h>
|
||||
#include <Editor/ViewManager.h>
|
||||
#include <CryCommon/MathConversion.h>
|
||||
|
||||
#include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h>
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
namespace
|
||||
{
|
||||
// This is a helper function that given an object that derives from QAbstractItemModel,
|
||||
// it will request the model's "ClassDataRole" class data for an entry and use that
|
||||
// information to create a new entity with the selected components.
|
||||
AZ::EntityId CreateEntityFromSelection(const QModelIndexList& selection, QAbstractItemModel* model)
|
||||
{
|
||||
AZ::Vector3 position = AZ::Vector3::CreateZero();
|
||||
CViewport *view = GetIEditor()->GetViewManager()->GetGameViewport();
|
||||
int width, height;
|
||||
view->GetDimensions(&width, &height);
|
||||
position = LYVec3ToAZVec3(view->ViewToWorld(QPoint(width / 2, height / 2)));
|
||||
|
||||
AZ::EntityId newEntityId;
|
||||
EBUS_EVENT_RESULT(newEntityId, AzToolsFramework::EditorRequests::Bus, CreateNewEntityAtPosition, position, AZ::EntityId());
|
||||
if (newEntityId.IsValid())
|
||||
{
|
||||
// Add all the selected components.
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto index : selection)
|
||||
{
|
||||
// We only need to consider the first column, it's important that the data() function that
|
||||
// returns ComponentDataModel::ClassDataRole also does so for the first column.
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariant classDataVariant = model->data(index, ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequestBus::Broadcast(&AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, AzToolsFramework::EntityIdList{ newEntityId }, componentsToAdd);
|
||||
|
||||
return newEntityId;
|
||||
}
|
||||
|
||||
return AZ::EntityId();
|
||||
}
|
||||
}
|
||||
|
||||
namespace ComponentDataUtilities
|
||||
{
|
||||
// This is a helper function to add the specified components to the selected entities, it relies on the provided
|
||||
// QAbstractItemModel to determine the appropriate ClassData to use to create the components (given that some widgets
|
||||
// may provide proxy models that alter the order).
|
||||
void AddComponentsToSelectedEntities(const QModelIndexList& selectedComponents, QAbstractItemModel* model)
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||
if (selectedEntities.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add all the selected components.
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto index : selectedComponents)
|
||||
{
|
||||
// We only need to consider the first column, it's important that the data() function that
|
||||
// returns ComponentDataModel::ClassDataRole also does so for the first column.
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVariant classDataVariant = model->data(index, ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequestBus::Broadcast(&AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, selectedEntities, componentsToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ComponentDataModel
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ComponentDataModel::ComponentDataModel(QObject* parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Failed to acquire application serialize context.");
|
||||
|
||||
serializeContext->EnumerateDerived<AZ::Component>([this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
|
||||
{
|
||||
bool allowed = false;
|
||||
bool hidden = false;
|
||||
AZStd::string category = "Miscellaneous";
|
||||
|
||||
if (classData->m_editData)
|
||||
{
|
||||
for (const AZ::Edit::ElementData& element : classData->m_editData->m_elements)
|
||||
{
|
||||
if (element.m_elementId == AZ::Edit::ClassElements::EditorData)
|
||||
{
|
||||
AZStd::string iconPath;
|
||||
AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
m_componentIcons[classData->m_typeId] = QIcon(iconPath.c_str());
|
||||
}
|
||||
|
||||
for (const AZ::Edit::AttributePair& attribPair : element.m_attributes)
|
||||
{
|
||||
if (attribPair.first == AZ::Edit::Attributes::AppearsInAddComponentMenu)
|
||||
{
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<AZ::Crc32>*>(attribPair.second))
|
||||
{
|
||||
if (data->Get(nullptr) == AZ_CRC("Game"))
|
||||
{
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attribPair.first == AZ::Edit::Attributes::AddableByUser)
|
||||
{
|
||||
// skip this component if user is not allowed to add it directly
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<bool>*>(attribPair.second))
|
||||
{
|
||||
if (!data->Get(nullptr))
|
||||
{
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attribPair.first == AZ::Edit::Attributes::Category)
|
||||
{
|
||||
if (auto data = azdynamic_cast<AZ::Edit::AttributeData<const char*>*>(attribPair.second))
|
||||
{
|
||||
category = data->Get(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allowed && !hidden)
|
||||
{
|
||||
m_componentList.push_back(classData);
|
||||
m_componentMap[category].push_back(classData);
|
||||
m_categories.insert(category);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// we'd like viewport events
|
||||
AzQtComponents::DragAndDropEventsBus::Handler::BusConnect(AzQtComponents::DragAndDropContexts::EditorViewport);
|
||||
}
|
||||
|
||||
ComponentDataModel::~ComponentDataModel()
|
||||
{
|
||||
AzQtComponents::DragAndDropEventsBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ComponentDataModel::flags([[maybe_unused]] const QModelIndex &index) const
|
||||
{
|
||||
return Qt::ItemFlags(
|
||||
Qt::ItemIsEnabled |
|
||||
Qt::ItemIsDragEnabled |
|
||||
Qt::ItemIsDropEnabled |
|
||||
Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
const AZ::SerializeContext::ClassData* ComponentDataModel::GetClassData(const QModelIndex& index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_componentList.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_componentList[row];
|
||||
}
|
||||
|
||||
const char* ComponentDataModel::GetCategory(const AZ::SerializeContext::ClassData* classData)
|
||||
{
|
||||
if (classData)
|
||||
{
|
||||
if (auto editorDataElement = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
|
||||
{
|
||||
if (auto categoryAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::Category))
|
||||
{
|
||||
if (auto categoryData = azdynamic_cast<AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
|
||||
{
|
||||
const char* result = categoryData->Get(nullptr);
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
QModelIndex ComponentDataModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
if (row >= rowCount(parent) || column >= columnCount(parent))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(row, column, (void*)(m_componentList[row]));
|
||||
}
|
||||
|
||||
QModelIndex ComponentDataModel::parent([[maybe_unused]] const QModelIndex &child) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int ComponentDataModel::rowCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return static_cast<int>(m_componentList.size());
|
||||
}
|
||||
|
||||
int ComponentDataModel::columnCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return ColumnIndex::Count;
|
||||
}
|
||||
|
||||
QVariant ComponentDataModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = m_componentList[index.row()];
|
||||
if (!classData)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case ClassDataRole:
|
||||
if (index.column() == 0) // Only get data for one column
|
||||
{
|
||||
return QVariant::fromValue<void*>(reinterpret_cast<void*>(const_cast<AZ::SerializeContext::ClassData*>(classData)));
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
if (index.column() == ColumnIndex::Name)
|
||||
{
|
||||
return QVariant(classData->m_editData->m_name);
|
||||
}
|
||||
else
|
||||
if (index.column() == ColumnIndex::Category)
|
||||
{
|
||||
if (auto editorDataElement = classData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData))
|
||||
{
|
||||
if (auto categoryAttribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::Category))
|
||||
{
|
||||
if (auto categoryData = azdynamic_cast<const AZ::Edit::AttributeData<const char*>*>(categoryAttribute))
|
||||
{
|
||||
return QVariant(categoryData->Get(nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
return QVariant(classData->m_editData->m_description);
|
||||
}
|
||||
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
if (index.column() == ColumnIndex::Icon)
|
||||
{
|
||||
auto iconIterator = m_componentIcons.find(classData->m_typeId);
|
||||
if (iconIterator != m_componentIcons.end())
|
||||
{
|
||||
return iconIterator->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QMimeData* ComponentDataModel::mimeData(const QModelIndexList& indices) const
|
||||
{
|
||||
QModelIndexList list;
|
||||
|
||||
// Filter out columns we are not interested in.
|
||||
for (const QModelIndex& index : indices)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
{
|
||||
list.push_back(index);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> sortedList;
|
||||
for (QModelIndex index : list)
|
||||
{
|
||||
QVariant classDataVariant = index.data(ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
sortedList.push_back(classData);
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData* mimeData = nullptr;
|
||||
if (!sortedList.empty())
|
||||
{
|
||||
mimeData = AzToolsFramework::ComponentTypeMimeData::Create(sortedList).release();
|
||||
}
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool ComponentDataModel::CanAcceptDragAndDropEvent(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) const
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzQtComponents;
|
||||
|
||||
// if a listener with a higher priority already claimed this event, do not touch it.
|
||||
if ((!event) || (event->isAccepted()) || (!event->mimeData()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ViewportDragContext* contextVP = azrtti_cast<ViewportDragContext*>(&context);
|
||||
if (!contextVP)
|
||||
{
|
||||
// not a viewport event. This is for some other GUI such as the main window itself.
|
||||
return false;
|
||||
}
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> componentClassDataList;
|
||||
return AzToolsFramework::ComponentTypeMimeData::Get(event->mimeData(), componentClassDataList);
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragEnter(QDragEnterEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
if (CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
// opportunities to show special highlights, or ghosted entities or previews here.
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragMove(QDragMoveEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
if (CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
// opportunities to update special highlights, or ghosted entities or previews here.
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentDataModel::DragLeave(QDragLeaveEvent* /*event*/)
|
||||
{
|
||||
// opportunities to remove ghosted entities or previews here.
|
||||
}
|
||||
|
||||
void ComponentDataModel::Drop(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context)
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzQtComponents;
|
||||
|
||||
// ALWAYS CHECK - you are not the only one connected to this bus, and someone else may have already
|
||||
// handled the event or accepted the drop - it might not contain types relevant to you.
|
||||
// you still get informed about the drop event in case you did some stuff in your gui and need to clean it up.
|
||||
if (!CanAcceptDragAndDropEvent(event, context))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// note that the above call already checks all the pointers such as event, or whether context is a VP context, mimetype, etc
|
||||
ViewportDragContext* contextVP = azrtti_cast<ViewportDragContext*>(&context);
|
||||
|
||||
// we don't get given this action by Qt unless we already returned accepted from one of the other ones (such as drag move of drag enter)
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->setAccepted(true);
|
||||
|
||||
AzToolsFramework::ScopedUndoBatch undo("Create entity from components");
|
||||
const AZStd::string name = AZStd::string::format("Entity%d", GetIEditor()->GetObjectManager()->GetObjectCount());
|
||||
|
||||
AZ::Entity* newEntity = aznew AZ::Entity(name.c_str());
|
||||
if (newEntity)
|
||||
{
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(&AzToolsFramework::EditorEntityContextRequests::AddRequiredComponents, *newEntity);
|
||||
auto* transformComponent = newEntity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldTM(AZ::Transform::CreateTranslation(contextVP->m_hitLocation));
|
||||
}
|
||||
|
||||
// Add the entity to the editor context, which activates it and creates the sandbox object.
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(&AzToolsFramework::EditorEntityContextRequests::AddEditorEntity, newEntity);
|
||||
|
||||
// Prepare undo command last so it captures the final state of the entity.
|
||||
AzToolsFramework::EntityCreateCommand* command = aznew AzToolsFramework::EntityCreateCommand(static_cast<AZ::u64>(newEntity->GetId()));
|
||||
command->Capture(newEntity);
|
||||
command->SetParent(undo.GetUndoBatch());
|
||||
|
||||
// Only need to add components to the new entity
|
||||
AzToolsFramework::EntityIdList entities = { newEntity->GetId() };
|
||||
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> componentClassDataList;
|
||||
AzToolsFramework::ComponentTypeMimeData::Get(event->mimeData(), componentClassDataList);
|
||||
|
||||
AZ::ComponentTypeList componentsToAdd;
|
||||
for (auto classData : componentClassDataList)
|
||||
{
|
||||
if (!classData)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
componentsToAdd.push_back(classData->m_typeId);
|
||||
}
|
||||
|
||||
AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome addedComponentsResult = AZ::Failure(AZStd::string("Failed to call AddComponentsToEntities on EntityCompositionRequestBus"));
|
||||
AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(addedComponentsResult, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, entities, componentsToAdd);
|
||||
|
||||
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::AddDirtyEntity, newEntity->GetId());
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities, entities);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::EntityId ComponentDataProxyModel::NewEntityFromSelection(const QModelIndexList& selection)
|
||||
{
|
||||
return CreateEntityFromSelection(selection, this);
|
||||
}
|
||||
|
||||
AZ::EntityId ComponentDataModel::NewEntityFromSelection(const QModelIndexList& selection)
|
||||
{
|
||||
return CreateEntityFromSelection(selection, this);
|
||||
}
|
||||
|
||||
bool ComponentDataProxyModel::filterAcceptsRow(int sourceRow, [[maybe_unused]] const QModelIndex &sourceParent) const
|
||||
{
|
||||
if (m_selectedCategory.empty() && !filterRegExp().isValid())
|
||||
return true;
|
||||
|
||||
ComponentDataModel* dataModel = static_cast<ComponentDataModel*>(sourceModel());
|
||||
if (sourceRow < 0 || sourceRow >= dataModel->GetComponents().size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::SerializeContext::ClassData* classData = dataModel->GetComponents()[sourceRow];
|
||||
if (!classData)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Category
|
||||
if (!m_selectedCategory.empty())
|
||||
{
|
||||
AZStd::string currentCateogry = ComponentDataModel::GetCategory(classData);
|
||||
|
||||
if (AzFramework::StringFunc::Find(currentCateogry.c_str(), m_selectedCategory.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filterRegExp().isValid())
|
||||
{
|
||||
QString componentName = QString::fromUtf8(classData->m_editData->m_name);
|
||||
return componentName.contains(filterRegExp());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ComponentDataProxyModel::SetSelectedCategory(const AZStd::string& category)
|
||||
{
|
||||
m_selectedCategory = category;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void ComponentDataProxyModel::ClearSelectedCategory()
|
||||
{
|
||||
m_selectedCategory.clear();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
#include "UI/ComponentPalette/moc_ComponentDataModel.cpp"
|
||||
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QAbstractTableModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
#include <AzQtComponents/Buses/DragAndDrop.h>
|
||||
#endif
|
||||
|
||||
namespace ComponentDataUtilities
|
||||
{
|
||||
// Given a list of selected components, use the provided model to get the components to add to any selected entities.
|
||||
void AddComponentsToSelectedEntities(const QModelIndexList& selectedComponents, QAbstractItemModel* model);
|
||||
}
|
||||
|
||||
class CViewport;
|
||||
|
||||
//! ComponentDataModel
|
||||
//! Holds the data required to display components in a table, this includes component name, categories, icons.
|
||||
class ComponentDataModel
|
||||
: public QAbstractTableModel
|
||||
, protected AzQtComponents::DragAndDropEventsBus::Handler // its okay if more than one of these is installed, the first one gets it.
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ComponentDataModel, AZ::SystemAllocator, 0);
|
||||
|
||||
using ComponentClassList = AZStd::vector<const AZ::SerializeContext::ClassData*>;
|
||||
using ComponentCategorySet = AZStd::set<AZStd::string>;
|
||||
using ComponentClassMap = AZStd::unordered_map<AZStd::string, AZStd::vector<const AZ::SerializeContext::ClassData*>>;
|
||||
using ComponentIconMap = AZStd::unordered_map<AZ::Uuid, QIcon>;
|
||||
|
||||
enum ColumnIndex
|
||||
{
|
||||
Icon,
|
||||
Category,
|
||||
Name,
|
||||
Count
|
||||
};
|
||||
|
||||
enum CustomRoles
|
||||
{
|
||||
ClassDataRole = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
ComponentDataModel(QObject* parent = nullptr);
|
||||
~ComponentDataModel() override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||
|
||||
const AZ::SerializeContext::ClassData* GetClassData(const QModelIndex&) const;
|
||||
|
||||
AZ::EntityId NewEntityFromSelection(const QModelIndexList& selection);
|
||||
|
||||
static const char* GetCategory(const AZ::SerializeContext::ClassData* classData);
|
||||
|
||||
ComponentClassList& GetComponents() { return m_componentList; }
|
||||
ComponentCategorySet& GetCategories() { return m_categories; }
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzQtComponents::DragAndDropEventsBus::Handler
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void DragEnter(QDragEnterEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
void DragMove(QDragMoveEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
void DragLeave(QDragLeaveEvent* event) override;
|
||||
void Drop(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) override;
|
||||
bool CanAcceptDragAndDropEvent(QDropEvent* event, AzQtComponents::DragAndDropContextBase& context) const;
|
||||
|
||||
ComponentClassList m_componentList;
|
||||
ComponentClassMap m_componentMap;
|
||||
ComponentIconMap m_componentIcons;
|
||||
ComponentCategorySet m_categories;
|
||||
};
|
||||
|
||||
//! ComponentDataProxyModel
|
||||
//! FilterProxy for the ComponentDataModel is used along with the search criteria to filter the
|
||||
//! list of components based on tags and/or selected category.
|
||||
class ComponentDataProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ComponentDataProxyModel, AZ::SystemAllocator, 0);
|
||||
|
||||
ComponentDataProxyModel(QObject* parent = nullptr)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{}
|
||||
|
||||
// Creates a new entity and adds the selected components to it.
|
||||
// It is specialized here to ensure it uses the correct indices according to the sorted data.
|
||||
AZ::EntityId NewEntityFromSelection(const QModelIndexList& selection);
|
||||
|
||||
// Filters rows according to the specifed tags and/or selected category
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
// Set the category to filter by.
|
||||
void SetSelectedCategory(const AZStd::string& category);
|
||||
void ClearSelectedCategory();
|
||||
|
||||
protected:
|
||||
|
||||
AZStd::string m_selectedCategory;
|
||||
};
|
||||
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ComponentPaletteWindow.h"
|
||||
#include "ComponentDataModel.h"
|
||||
#include "FavoriteComponentList.h"
|
||||
#include "FilteredComponentList.h"
|
||||
#include "CategoriesList.h"
|
||||
|
||||
#include <LyViewPaneNames.h>
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
#include <AzToolsFramework/UI/SearchWidget/SearchCriteriaWidget.hxx>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/ViewPaneOptions.h>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QKeyEvent>
|
||||
|
||||
ComponentPaletteWindow::ComponentPaletteWindow(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void ComponentPaletteWindow::Init()
|
||||
{
|
||||
layout()->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
QHBoxLayout* gridLayout = new QHBoxLayout(nullptr);
|
||||
gridLayout->setSizeConstraint(QLayout::SetMaximumSize);
|
||||
gridLayout->setContentsMargins(0, 0, 0, 0);
|
||||
gridLayout->setSpacing(0);
|
||||
|
||||
m_filterWidget = new AzToolsFramework::SearchCriteriaWidget(this);
|
||||
|
||||
QStringList tags;
|
||||
tags << tr("name");
|
||||
m_filterWidget->SetAcceptedTags(tags, tags[0]);
|
||||
layout->addLayout(gridLayout, 1);
|
||||
|
||||
// Left Panel
|
||||
QVBoxLayout* leftPaneLayout = new QVBoxLayout(this);
|
||||
|
||||
// Favorites
|
||||
leftPaneLayout->addWidget(new QLabel(tr("Favorites")));
|
||||
leftPaneLayout->addWidget(new QLabel(tr("Drag components here to add favorites.")));
|
||||
FavoritesList* favorites = new FavoritesList();
|
||||
favorites->Init();
|
||||
leftPaneLayout->addWidget(favorites);
|
||||
|
||||
// Categories
|
||||
m_categoryListWidget = new ComponentCategoryList();
|
||||
m_categoryListWidget->Init();
|
||||
leftPaneLayout->addWidget(m_categoryListWidget);
|
||||
gridLayout->addLayout(leftPaneLayout);
|
||||
|
||||
// Right Panel
|
||||
QVBoxLayout* rightPanelLayout = new QVBoxLayout(this);
|
||||
gridLayout->addLayout(rightPanelLayout);
|
||||
|
||||
// Component list
|
||||
m_componentListWidget = new FilteredComponentList(this);
|
||||
m_componentListWidget->Init();
|
||||
|
||||
rightPanelLayout->addWidget(new QLabel(tr("Components")));
|
||||
rightPanelLayout->addWidget(m_filterWidget, 0, Qt::AlignTop);
|
||||
rightPanelLayout->addWidget(m_componentListWidget);
|
||||
|
||||
// The main window
|
||||
QWidget* window = new QWidget();
|
||||
window->setLayout(layout);
|
||||
setCentralWidget(window);
|
||||
|
||||
connect(m_categoryListWidget, &ComponentCategoryList::OnCategoryChange, m_componentListWidget, &FilteredComponentList::SetCategory);
|
||||
connect(m_filterWidget, &AzToolsFramework::SearchCriteriaWidget::SearchCriteriaChanged, m_componentListWidget, &FilteredComponentList::SearchCriteriaChanged);
|
||||
|
||||
}
|
||||
|
||||
void ComponentPaletteWindow::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_F)
|
||||
{
|
||||
m_filterWidget->SelectTextEntryBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMainWindow::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentPaletteWindow::RegisterViewClass()
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
|
||||
ViewPaneOptions options;
|
||||
options.canHaveMultipleInstances = true;
|
||||
RegisterViewPane<ComponentPaletteWindow>("Component Palette", LyViewPane::CategoryOther, options);
|
||||
}
|
||||
|
||||
#include <UI/ComponentPalette/moc_ComponentPaletteWindow.cpp>
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <QMainWindow>
|
||||
#include <AzCore/Math/Guid.h>
|
||||
#endif
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class SearchCriteriaWidget;
|
||||
}
|
||||
|
||||
class ComponentCategoryList;
|
||||
class FilteredComponentList;
|
||||
class ComponentDataModel;
|
||||
|
||||
//! ComponentPaletteWindow
|
||||
//! Provides a window with controls related to the Component Entity system. It provides an intuitive and organized
|
||||
//! set of controls to display, sort, filter components. It provides mechanisms for creating entities by dragging
|
||||
//! and dropping components into the viewport as well as from context menus.
|
||||
class ComponentPaletteWindow
|
||||
: public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ComponentPaletteWindow(QWidget* parent = 0);
|
||||
|
||||
void Init();
|
||||
|
||||
static const GUID& GetClassID()
|
||||
{
|
||||
// {4236998F-1138-466D-9DF5-6533BFA1DFCA}
|
||||
static const GUID guid =
|
||||
{
|
||||
0x4236998F, 0x1138, 0x466D, { 0x9D, 0xF5, 0x65, 0x33, 0xBF, 0xA1, 0xDF, 0xCA }
|
||||
};
|
||||
return guid;
|
||||
}
|
||||
|
||||
static void RegisterViewClass();
|
||||
|
||||
protected:
|
||||
ComponentCategoryList* m_categoryListWidget;
|
||||
FilteredComponentList* m_componentListWidget;
|
||||
AzToolsFramework::SearchCriteriaWidget* m_filterWidget;
|
||||
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
};
|
||||
@ -1,392 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FavoriteComponentList.h"
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <Editor/CryEditDoc.h>
|
||||
#include <Editor/ViewManager.h>
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QMimeData>
|
||||
|
||||
// FavoritesList
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FavoritesList::FavoritesList(QWidget* parent /*= nullptr*/)
|
||||
: FilteredComponentList(parent)
|
||||
{
|
||||
}
|
||||
|
||||
FavoritesList::~FavoritesList()
|
||||
{
|
||||
FavoriteComponentListRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void FavoritesList::Init()
|
||||
{
|
||||
FavoriteComponentListRequestBus::Handler::BusConnect();
|
||||
|
||||
FavoritesDataModel* favoritesDataModel = new FavoritesDataModel(this);
|
||||
|
||||
setModel(favoritesDataModel);
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(ComponentDataModel::ColumnIndex::Name, QHeaderView::Stretch);
|
||||
|
||||
setShowGrid(false);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||||
setStyleSheet("QTableView { selection-background-color: rgba(255,255,255,0.2); }");
|
||||
setGridStyle(Qt::PenStyle::NoPen);
|
||||
verticalHeader()->hide();
|
||||
horizontalHeader()->hide();
|
||||
setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
|
||||
setShowGrid(false);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
|
||||
setColumnWidth(ComponentDataModel::ColumnIndex::Icon, 32);
|
||||
hideColumn(ComponentDataModel::ColumnIndex::Category);
|
||||
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
setAcceptDrops(true);
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(ComponentDataModel::ColumnIndex::Icon, QHeaderView::ResizeToContents);
|
||||
setColumnWidth(ComponentDataModel::ColumnIndex::Icon, 32);
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(ComponentDataModel::ColumnIndex::Category, QHeaderView::Stretch);
|
||||
setColumnWidth(ComponentDataModel::ColumnIndex::Category, 90);
|
||||
|
||||
// Context menu
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &QWidget::customContextMenuRequested, this, &FavoritesList::ShowContextMenu);
|
||||
}
|
||||
|
||||
void FavoritesList::ShowContextMenu(const QPoint& pos)
|
||||
{
|
||||
// Only show if a level is loaded
|
||||
if (!GetIEditor() || GetIEditor()->IsInGameMode())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( model()->rowCount() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu contextMenu(tr("Context menu"), this);
|
||||
|
||||
QAction actionNewEntity(tr("Make entity with selected favorites"), this);
|
||||
QAction actionAddToSelection(this);
|
||||
if (GetIEditor()->GetDocument()->IsDocumentReady())
|
||||
{
|
||||
QObject::connect(&actionNewEntity, &QAction::triggered, this, [&] { ContextMenu_NewEntity(); });
|
||||
contextMenu.addAction(&actionNewEntity);
|
||||
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
EBUS_EVENT_RESULT(selectedEntities, AzToolsFramework::ToolsApplicationRequests::Bus, GetSelectedEntities);
|
||||
|
||||
if (!selectedEntities.empty())
|
||||
{
|
||||
QString addToSelection = selectedEntities.size() > 1 ? tr("Add to selected entities") : tr("Add to selected entity");
|
||||
actionAddToSelection.setText(addToSelection);
|
||||
|
||||
QObject::connect(&actionAddToSelection, &QAction::triggered, this, [&] { ContextMenu_AddToSelectedEntities(); });
|
||||
contextMenu.addAction(&actionAddToSelection);
|
||||
}
|
||||
|
||||
contextMenu.addSeparator();
|
||||
}
|
||||
|
||||
QAction action(tr("Remove"), this);
|
||||
QObject::connect(&action, &QAction::triggered, this, [&] { ContextMenu_RemoveSelectedFavorites(); });
|
||||
contextMenu.addAction(&action);
|
||||
|
||||
contextMenu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void FavoritesList::ContextMenu_RemoveSelectedFavorites()
|
||||
{
|
||||
FavoritesDataModel* dataModel = qobject_cast<FavoritesDataModel*>(model());
|
||||
if (!selectedIndexes().empty())
|
||||
{
|
||||
dataModel->Remove(selectedIndexes());
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesList::rowsInserted([[maybe_unused]] const QModelIndex& parent, [[maybe_unused]] int start, [[maybe_unused]] int end)
|
||||
{
|
||||
resizeRowToContents(0);
|
||||
}
|
||||
|
||||
void FavoritesList::AddFavorites(const AZStd::vector<const AZ::SerializeContext::ClassData*>& classDataContainer)
|
||||
{
|
||||
for (const AZ::SerializeContext::ClassData* classData : classDataContainer)
|
||||
{
|
||||
if (classData)
|
||||
{
|
||||
FavoritesDataModel* dataModel = qobject_cast<FavoritesDataModel*>(model());
|
||||
dataModel->AddFavorite(classData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesList::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
if (event->mimeData()->hasFormat(AzToolsFramework::ComponentTypeMimeData::GetMimeType()))
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesList::dragMoveEvent(QDragMoveEvent* event)
|
||||
{
|
||||
if (event->source() == this)
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
// FavoritesDataModel
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int FavoritesDataModel::rowCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return m_favorites.size();
|
||||
}
|
||||
|
||||
int FavoritesDataModel::columnCount([[maybe_unused]] const QModelIndex &parent /*= QModelIndex()*/) const
|
||||
{
|
||||
return ColumnIndex::Count;
|
||||
}
|
||||
|
||||
void FavoritesDataModel::SaveState()
|
||||
{
|
||||
AZStd::vector<AZ::Uuid> favorites;
|
||||
for (const AZ::SerializeContext::ClassData* classData : m_favorites)
|
||||
{
|
||||
favorites.push_back(classData->m_typeId);
|
||||
}
|
||||
m_settings->SetFavorites(AZStd::move(favorites));
|
||||
|
||||
|
||||
// Write the settings to file...
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Serialize Context is null!");
|
||||
|
||||
char settingsPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath(ComponentPaletteSettings::GetSettingsFile(), settingsPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
bool result = m_provider.Save(settingsPath, serializeContext);
|
||||
(void)result;
|
||||
AZ_Warning("ComponentPaletteSettings", result, "Failed to Save the Component Palette Settings!");
|
||||
}
|
||||
|
||||
void FavoritesDataModel::LoadState()
|
||||
{
|
||||
// It is necessary to Load the settings file *before* you call UserSettings::CreateFind!
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
AZ_Assert(serializeContext, "Serialize Context is null!");
|
||||
|
||||
char settingsPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath(ComponentPaletteSettings::GetSettingsFile(), settingsPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
bool result = m_provider.Load(settingsPath, serializeContext);
|
||||
(void)result;
|
||||
|
||||
|
||||
// Create (if no file was found) or find the settings, this will populate the m_settings->m_favorites list.
|
||||
m_settings = AZ::UserSettings::CreateFind<ComponentPaletteSettings>(AZ_CRC("ComponentPaletteSettings", 0x481d355b), m_providerId);
|
||||
|
||||
// Add favorites to the data model from loaded settings
|
||||
for (const AZ::Uuid& favorite : m_settings->m_favorites)
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(favorite);
|
||||
if (classData)
|
||||
{
|
||||
AddFavorite(classData, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritesDataModel::Remove(const QModelIndexList& indices)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
auto newFavorites = m_favorites;
|
||||
|
||||
// swap here
|
||||
for (auto index : indices)
|
||||
{
|
||||
// we're only dealing with columns and they're the only thing with class data anyways
|
||||
if (index.column() == 0)
|
||||
{
|
||||
QVariant classDataVariant = index.data(ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
newFavorites.removeAll(classData);
|
||||
|
||||
AZ_TracePrintf("Debug", "Removing: %s\n", classData->m_editData->m_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_favorites.swap(newFavorites);
|
||||
|
||||
endResetModel();
|
||||
|
||||
SaveState();
|
||||
}
|
||||
|
||||
QModelIndex FavoritesDataModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
if (row >= rowCount(parent) || column >= columnCount(parent))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(row, column, (void*)(m_favorites[row]));
|
||||
}
|
||||
|
||||
QVariant FavoritesDataModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const AZ::SerializeContext::ClassData* classData = m_favorites[index.row()];
|
||||
if (!classData)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
if (index.column() == ComponentDataModel::ColumnIndex::Name)
|
||||
{
|
||||
if (m_favorites.empty())
|
||||
{
|
||||
return QVariant(tr("You have 0 favorites.\nDrag some components here."));
|
||||
}
|
||||
|
||||
return QVariant(classData->m_editData->m_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
if (index.column() == ColumnIndex::Icon)
|
||||
{
|
||||
const AZ::SerializeContext::ClassData* iconClassData = m_favorites[index.row()];
|
||||
auto iconIterator = m_componentIcons.find(iconClassData->m_typeId);
|
||||
if (iconIterator != m_componentIcons.end())
|
||||
{
|
||||
return iconIterator->second;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ClassDataRole:
|
||||
if (index.column() == 0) // Only get data for one column
|
||||
{
|
||||
return QVariant::fromValue<void*>(reinterpret_cast<void*>(const_cast<AZ::SerializeContext::ClassData*>(classData)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ComponentDataModel::data(index, role);
|
||||
|
||||
}
|
||||
|
||||
void FavoritesDataModel::SetSavedStateKey([[maybe_unused]] AZ::u32 key)
|
||||
{
|
||||
}
|
||||
|
||||
FavoritesDataModel::FavoritesDataModel(QWidget* parent /*= nullptr*/)
|
||||
: ComponentDataModel(parent)
|
||||
, m_providerId(AZ_CRC("ComponentPaletteSettingsProviderId"))
|
||||
{
|
||||
m_provider.Activate(m_providerId);
|
||||
LoadState();
|
||||
}
|
||||
|
||||
FavoritesDataModel::~FavoritesDataModel()
|
||||
{
|
||||
m_provider.Deactivate();
|
||||
}
|
||||
|
||||
void FavoritesDataModel::AddFavorite(const AZ::SerializeContext::ClassData* classData, bool updateSettings)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
if (m_favorites.indexOf(classData) < 0)
|
||||
{
|
||||
m_favorites.push_back(classData);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
if (updateSettings)
|
||||
{
|
||||
SaveState();
|
||||
}
|
||||
}
|
||||
|
||||
bool FavoritesDataModel::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex &parent)
|
||||
{
|
||||
if (action == Qt::IgnoreAction)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (data && data->hasFormat(AzToolsFramework::ComponentTypeMimeData::GetMimeType()))
|
||||
{
|
||||
AzToolsFramework::ComponentTypeMimeData::ClassDataContainer classDataContainer;
|
||||
AzToolsFramework::ComponentTypeMimeData::Get(data, classDataContainer);
|
||||
|
||||
for (const AZ::SerializeContext::ClassData* classData : classDataContainer)
|
||||
{
|
||||
if (classData)
|
||||
{
|
||||
AddFavorite(classData);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <UI/ComponentPalette/moc_FavoriteComponentList.cpp>
|
||||
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ComponentDataModel.h"
|
||||
#include "FilteredComponentList.h"
|
||||
#include "ComponentPaletteSettings.h"
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
|
||||
#endif
|
||||
|
||||
//! FavoriteComponentListRequest
|
||||
//! Bus that provides a way for external features to record favorites
|
||||
class FavoriteComponentListRequest : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
virtual void AddFavorites(const AZStd::vector<const AZ::SerializeContext::ClassData*>&) = 0;
|
||||
};
|
||||
|
||||
using FavoriteComponentListRequestBus = AZ::EBus<FavoriteComponentListRequest>;
|
||||
|
||||
|
||||
//! FavoritesDataModel
|
||||
//! Stores the list of component class data to display in the favorites control, offers persistence through user settings.
|
||||
class FavoritesDataModel
|
||||
: public ComponentDataModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AZ_CLASS_ALLOCATOR(FavoritesDataModel, AZ::SystemAllocator, 0);
|
||||
|
||||
FavoritesDataModel(QWidget* parent = nullptr);
|
||||
~FavoritesDataModel() override;
|
||||
|
||||
//! Add a favorite component
|
||||
//! \param classData The ClassData information for the component to store as favorite
|
||||
//! \param updateSettings Optional parameter used to determine if the persistent settings need to be updated.
|
||||
void AddFavorite(const AZ::SerializeContext::ClassData* classData, bool updateSettings = true);
|
||||
|
||||
//! Remove all the specified items from the table
|
||||
//! \param indices List of indices to remove from favorites
|
||||
void Remove(const QModelIndexList& indices);
|
||||
|
||||
//! Save the list of favorite components to user settings
|
||||
void SaveState();
|
||||
|
||||
//! Load the list of favorite components from user settings
|
||||
void LoadState();
|
||||
|
||||
protected:
|
||||
|
||||
void SetSavedStateKey(AZ::u32 key);
|
||||
|
||||
// Qt handlers
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
|
||||
// List of component class data
|
||||
QList<const AZ::SerializeContext::ClassData*> m_favorites;
|
||||
|
||||
// The Palette settings and provider information for saving out the Favorites list
|
||||
AZStd::intrusive_ptr<ComponentPaletteSettings> m_settings;
|
||||
AZ::UserSettingsProvider m_provider;
|
||||
AZ::u32 m_providerId;
|
||||
};
|
||||
|
||||
|
||||
//! FavoritesList
|
||||
//! User customized list of favorite components, provides persistence.
|
||||
class FavoritesList
|
||||
: public FilteredComponentList
|
||||
, FavoriteComponentListRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit FavoritesList(QWidget* parent = nullptr);
|
||||
~FavoritesList() override;
|
||||
|
||||
void Init() override;
|
||||
|
||||
protected:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FavoriteComponentListRequestBus
|
||||
void AddFavorites(const AZStd::vector<const AZ::SerializeContext::ClassData*>& classDataContainer) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void rowsInserted(const QModelIndex& parent, int start, int end) override;
|
||||
|
||||
// Context menu handlers
|
||||
void ShowContextMenu(const QPoint&);
|
||||
void ContextMenu_RemoveSelectedFavorites();
|
||||
|
||||
// Validate data being dragged in
|
||||
void dragEnterEvent(QDragEnterEvent * event) override;
|
||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||
|
||||
//! Handler used when dropping PaletteItems into the Viewport.
|
||||
static void DragDropHandler(CViewport* viewport, int ptx, int pty, void* custom);
|
||||
};
|
||||
@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ComponentDataModel.h"
|
||||
#include "FavoriteComponentList.h"
|
||||
#include "FilteredComponentList.h"
|
||||
|
||||
#include "CryCommon/MathConversion.h"
|
||||
#include "Editor/IEditor.h"
|
||||
#include "Editor/ViewManager.h"
|
||||
#include <Editor/CryEditDoc.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
void FilteredComponentList::Init()
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setDragDropMode(QAbstractItemView::DragDropMode::DragOnly);
|
||||
setDragEnabled(true);
|
||||
|
||||
setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||||
setStyleSheet("QTreeWidget { selection-background-color: rgba(255,255,255,0.2); }");
|
||||
setGridStyle(Qt::PenStyle::NoPen);
|
||||
verticalHeader()->hide();
|
||||
horizontalHeader()->hide();
|
||||
setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
|
||||
setAcceptDrops(false);
|
||||
|
||||
m_componentDataModel = new ComponentDataModel(this);
|
||||
ComponentDataProxyModel* componentDataProxyModel = new ComponentDataProxyModel(this);
|
||||
componentDataProxyModel->setSourceModel(m_componentDataModel);
|
||||
setModel(componentDataProxyModel);
|
||||
|
||||
QHeaderView* horizontalHeaderView = horizontalHeader();
|
||||
horizontalHeaderView->setSectionResizeMode(ComponentDataModel::ColumnIndex::Icon, QHeaderView::ResizeToContents);
|
||||
horizontalHeaderView->setSectionResizeMode(ComponentDataModel::ColumnIndex::Name, QHeaderView::Stretch);
|
||||
|
||||
setColumnWidth(ComponentDataModel::ColumnIndex::Icon, 32);
|
||||
setShowGrid(false);
|
||||
|
||||
setColumnWidth(ComponentDataModel::ColumnIndex::Name, 90);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
|
||||
sortByColumn(ComponentDataModel::ColumnIndex::Name, Qt::AscendingOrder);
|
||||
hideColumn(ComponentDataModel::ColumnIndex::Category);
|
||||
|
||||
connect(model(), &QAbstractItemModel::rowsInserted, this, &FilteredComponentList::rowsInserted);
|
||||
connect(model(), &QAbstractItemModel::rowsRemoved, this, &FilteredComponentList::rowsAboutToBeRemoved);
|
||||
|
||||
connect(model(), SIGNAL(modelReset()), SLOT(modelReset()));
|
||||
|
||||
|
||||
// Context menu
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &QWidget::customContextMenuRequested, this, &FilteredComponentList::ShowContextMenu);
|
||||
}
|
||||
|
||||
void FilteredComponentList::ContextMenu_NewEntity()
|
||||
{
|
||||
AZ::EntityId entityId;
|
||||
|
||||
auto proxyDataModel = qobject_cast<ComponentDataProxyModel*>(model());
|
||||
if (proxyDataModel)
|
||||
{
|
||||
entityId = proxyDataModel->NewEntityFromSelection(selectedIndexes());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dataModel = qobject_cast<ComponentDataModel*>(model());
|
||||
if (dataModel)
|
||||
{
|
||||
entityId = dataModel->NewEntityFromSelection(selectedIndexes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FilteredComponentList::ContextMenu_AddToFavorites()
|
||||
{
|
||||
AZStd::vector<const AZ::SerializeContext::ClassData*> componentsToAdd;
|
||||
for (auto index : selectedIndexes())
|
||||
{
|
||||
QVariant classDataVariant = index.data(ComponentDataModel::ClassDataRole);
|
||||
if (classDataVariant.isValid())
|
||||
{
|
||||
auto classData = reinterpret_cast<const AZ::SerializeContext::ClassData*>(classDataVariant.value<void*>());
|
||||
componentsToAdd.push_back(classData);
|
||||
}
|
||||
}
|
||||
|
||||
if (!componentsToAdd.empty())
|
||||
{
|
||||
EBUS_EVENT(FavoriteComponentListRequestBus, AddFavorites, componentsToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredComponentList::ContextMenu_AddToSelectedEntities()
|
||||
{
|
||||
ComponentDataUtilities::AddComponentsToSelectedEntities(selectedIndexes(), model());
|
||||
}
|
||||
|
||||
void FilteredComponentList::ShowContextMenu(const QPoint& pos)
|
||||
{
|
||||
QMenu contextMenu(tr("Context menu"), this);
|
||||
|
||||
QAction actionNewEntity(tr("Create new entity with selected components"), this);
|
||||
if (GetIEditor()->GetDocument()->IsDocumentReady())
|
||||
{
|
||||
QObject::connect(&actionNewEntity, &QAction::triggered, this, [this] { ContextMenu_NewEntity(); });
|
||||
contextMenu.addAction(&actionNewEntity);
|
||||
}
|
||||
|
||||
QAction actionAddFavorite(tr("Add to favorites"), this);
|
||||
QObject::connect(&actionAddFavorite, &QAction::triggered, this, [this] { ContextMenu_AddToFavorites(); });
|
||||
contextMenu.addAction(&actionAddFavorite);
|
||||
|
||||
QAction actionAddToSelection(this);
|
||||
if (GetIEditor()->GetDocument()->IsDocumentReady())
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntities;
|
||||
EBUS_EVENT_RESULT(selectedEntities, AzToolsFramework::ToolsApplicationRequests::Bus, GetSelectedEntities);
|
||||
|
||||
if (!selectedEntities.empty())
|
||||
{
|
||||
QString addToSelection = selectedEntities.size() > 1 ? tr("Add to selected entities") : tr("Add to selected entity");
|
||||
|
||||
actionAddToSelection.setText(addToSelection);
|
||||
QObject::connect(&actionAddToSelection, &QAction::triggered, this, [this] { ContextMenu_AddToSelectedEntities(); });
|
||||
contextMenu.addAction(&actionAddToSelection);
|
||||
}
|
||||
}
|
||||
// TODO: Requires information panel implementation LMBR-28174
|
||||
//QAction actionHelp(tr("Help"), this);
|
||||
//QObject::connect(&actionHelp, &QAction::triggered, this, [&] {});
|
||||
//contextMenu.addAction(&actionHelp);
|
||||
|
||||
contextMenu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void FilteredComponentList::modelReset()
|
||||
{
|
||||
// Ensure that the category column is hidden
|
||||
hideColumn(ComponentDataModel::ColumnIndex::Category);
|
||||
}
|
||||
|
||||
FilteredComponentList::FilteredComponentList(QWidget* parent /*= nullptr*/)
|
||||
: QTableView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
FilteredComponentList::~FilteredComponentList()
|
||||
{
|
||||
}
|
||||
|
||||
void FilteredComponentList::SearchCriteriaChanged(QStringList& criteriaList, AzToolsFramework::FilterOperatorType filterOperator)
|
||||
{
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
auto dataModel = qobject_cast<ComponentDataProxyModel*>(model());
|
||||
if (dataModel)
|
||||
{
|
||||
// Go through the list of items and show/hide as needed due to filter.
|
||||
QString filter;
|
||||
for (const auto& criteria : criteriaList)
|
||||
{
|
||||
QString tag, text;
|
||||
AzToolsFramework::SearchCriteriaButton::SplitTagAndText(criteria, tag, text);
|
||||
AppendFilter(filter, text, filterOperator);
|
||||
}
|
||||
|
||||
dataModel->setFilterRegExp(QRegExp(filter, Qt::CaseSensitivity::CaseInsensitive));
|
||||
}
|
||||
|
||||
setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void FilteredComponentList::SetCategory(const char* category)
|
||||
{
|
||||
auto dataModel = qobject_cast<ComponentDataProxyModel*>(model());
|
||||
if (dataModel)
|
||||
{
|
||||
if (!category || category[0] == 0 || azstricmp(category, "All") == 0)
|
||||
{
|
||||
dataModel->ClearSelectedCategory();
|
||||
}
|
||||
else
|
||||
{
|
||||
dataModel->SetSelectedCategory(category);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this ensures the category column remains hidden
|
||||
hideColumn(ComponentDataModel::ColumnIndex::Category);
|
||||
}
|
||||
|
||||
void FilteredComponentList::BuildFilter(QStringList& criteriaList, AzToolsFramework::FilterOperatorType filterOperator)
|
||||
{
|
||||
ClearFilterRegExp();
|
||||
|
||||
for (const auto& criteria : criteriaList)
|
||||
{
|
||||
QString tag, text;
|
||||
AzToolsFramework::SearchCriteriaButton::SplitTagAndText(criteria, tag, text);
|
||||
if (tag.isEmpty())
|
||||
{
|
||||
tag = "null";
|
||||
}
|
||||
|
||||
QString filter = m_filtersRegExp[tag.toStdString().c_str()].pattern();
|
||||
|
||||
AppendFilter(filter, text, filterOperator);
|
||||
|
||||
SetFilterRegExp(tag.toStdString().c_str(), QRegExp(filter, Qt::CaseInsensitive));
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredComponentList::AppendFilter(QString& filter, const QString& text, AzToolsFramework::FilterOperatorType filterOperator)
|
||||
{
|
||||
if (filterOperator == AzToolsFramework::FilterOperatorType::Or)
|
||||
{
|
||||
if (filter.isEmpty())
|
||||
{
|
||||
filter = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
filter += "|" + text;
|
||||
}
|
||||
}
|
||||
else if (filterOperator == AzToolsFramework::FilterOperatorType::And)
|
||||
{
|
||||
//using lookaheads to produce an "and" effect.
|
||||
filter += "(?=.*" + text + ")";
|
||||
}
|
||||
}
|
||||
|
||||
void FilteredComponentList::SetFilterRegExp(const AZStd::string& filterType, const QRegExp& regExp)
|
||||
{
|
||||
m_filtersRegExp[filterType] = regExp;
|
||||
}
|
||||
|
||||
void FilteredComponentList::ClearFilterRegExp(const AZStd::string& filterType /*= AZStd::string()*/)
|
||||
{
|
||||
if (filterType.empty())
|
||||
{
|
||||
for (auto& it : m_filtersRegExp)
|
||||
{
|
||||
it.second = QRegExp();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filtersRegExp[filterType] = QRegExp();
|
||||
}
|
||||
}
|
||||
|
||||
#include <UI/ComponentPalette/moc_FilteredComponentList.cpp>
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QTableView>
|
||||
#include <QWidget>
|
||||
|
||||
#include <AzToolsFramework/UI/SearchWidget/SearchCriteriaWidget.hxx>
|
||||
#include <AzToolsFramework/UI/SearchWidget/SearchWidgetTypes.hxx>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include "ComponentDataModel.h"
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class SerializeContext;
|
||||
class ClassData;
|
||||
}
|
||||
|
||||
class ComponentDataModel;
|
||||
|
||||
//! FilteredComponentList
|
||||
//! Provides a list of components that can be filtered according to search criteria provided and/or from
|
||||
//! a category selection control.
|
||||
class FilteredComponentList
|
||||
: public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit FilteredComponentList(QWidget* parent = nullptr);
|
||||
|
||||
~FilteredComponentList() override;
|
||||
|
||||
virtual void Init();
|
||||
|
||||
void SearchCriteriaChanged(QStringList& criteriaList, AzToolsFramework::FilterOperatorType filterOperator);
|
||||
|
||||
void SetCategory(const char* category);
|
||||
|
||||
protected:
|
||||
|
||||
// Filtering support
|
||||
void BuildFilter(QStringList& criteriaList, AzToolsFramework::FilterOperatorType filterOperator);
|
||||
void AppendFilter(QString& filter, const QString& text, AzToolsFramework::FilterOperatorType filterOperator);
|
||||
void SetFilterRegExp(const AZStd::string& filterType, const QRegExp& regExp);
|
||||
void ClearFilterRegExp(const AZStd::string& filterType = AZStd::string());
|
||||
|
||||
// Context menu handlers
|
||||
void ShowContextMenu(const QPoint&);
|
||||
void ContextMenu_NewEntity();
|
||||
void ContextMenu_AddToFavorites();
|
||||
void ContextMenu_AddToSelectedEntities();
|
||||
|
||||
void modelReset();
|
||||
|
||||
AzToolsFramework::FilterByCategoryMap m_filtersRegExp;
|
||||
ComponentDataModel* m_componentDataModel;
|
||||
|
||||
};
|
||||
@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "InformationPanel.h"
|
||||
|
||||
// TODO: LMBR-28174
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// TODO: LMBR-28174
|
||||
@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "../../Editor/RenderHelpers/AxisHelperShared.inl"
|
||||
@ -1,700 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// Copied utils functions from CryPhysics that are used by non-physics systems
|
||||
// This functions will be eventually removed, DO *NOT* use these functions
|
||||
// TO-DO: Re-implement users using new code
|
||||
// LY-109806
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Cry_Math.h"
|
||||
|
||||
namespace LegacyCryPhysicsUtils
|
||||
{
|
||||
namespace polynomial_tpl_IMPL
|
||||
{
|
||||
template<class ftype, int degree>
|
||||
class polynomial_tpl
|
||||
{
|
||||
public:
|
||||
explicit polynomial_tpl() { denom = (ftype)1; };
|
||||
explicit polynomial_tpl(ftype op) { zero(); data[degree] = op; }
|
||||
AZ_FORCE_INLINE polynomial_tpl& zero()
|
||||
{
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
data[i] = 0;
|
||||
}
|
||||
denom = (ftype)1;
|
||||
return *this;
|
||||
}
|
||||
polynomial_tpl(const polynomial_tpl<ftype, degree>& src) { *this = src; }
|
||||
polynomial_tpl& operator=(const polynomial_tpl<ftype, degree>& src)
|
||||
{
|
||||
denom = src.denom;
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
data[i] = src.data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template<int degree1>
|
||||
AZ_FORCE_INLINE polynomial_tpl& operator=(const polynomial_tpl<ftype, degree1>& src)
|
||||
{
|
||||
int i;
|
||||
denom = src.denom;
|
||||
for (i = 0; i <= min(degree, degree1); i++)
|
||||
{
|
||||
data[i] = src.data[i];
|
||||
}
|
||||
for (; i < degree; i++)
|
||||
{
|
||||
data[i] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
AZ_FORCE_INLINE polynomial_tpl& set(ftype* pdata)
|
||||
{
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
data[degree - i] = pdata[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE ftype& operator[](int idx) { return data[idx]; }
|
||||
|
||||
void calc_deriviative(polynomial_tpl<ftype, degree>& deriv, int curdegree = degree) const;
|
||||
|
||||
AZ_FORCE_INLINE polynomial_tpl& fixsign()
|
||||
{
|
||||
ftype sg = sgnnz(denom);
|
||||
denom *= sg;
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
data[i] *= sg;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int findroots(ftype start, ftype end, ftype* proots, int nIters = 20, int curdegree = degree, bool noDegreeCheck = false) const;
|
||||
int nroots(ftype start, ftype end) const;
|
||||
|
||||
AZ_FORCE_INLINE ftype eval(ftype x) const
|
||||
{
|
||||
ftype res = 0;
|
||||
for (int i = degree; i >= 0; i--)
|
||||
{
|
||||
res = res * x + data[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
AZ_FORCE_INLINE ftype eval(ftype x, int subdegree) const
|
||||
{
|
||||
ftype res = data[subdegree];
|
||||
for (int i = subdegree - 1; i >= 0; i--)
|
||||
{
|
||||
res = res * x + data[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE polynomial_tpl& operator+=(ftype op) { data[0] += op * denom; return *this; }
|
||||
AZ_FORCE_INLINE polynomial_tpl& operator-=(ftype op) { data[0] -= op * denom; return *this; }
|
||||
AZ_FORCE_INLINE polynomial_tpl operator*(ftype op) const
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res;
|
||||
res.denom = denom;
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
res.data[i] = data[i] * op;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
AZ_FORCE_INLINE polynomial_tpl& operator*=(ftype op)
|
||||
{
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
data[i] *= op;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
AZ_FORCE_INLINE polynomial_tpl operator/(ftype op) const
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res = *this;
|
||||
res.denom = denom * op;
|
||||
return res;
|
||||
}
|
||||
AZ_FORCE_INLINE polynomial_tpl& operator/=(ftype op) { denom *= op; return *this; }
|
||||
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree * 2> sqr() const { return *this * *this; }
|
||||
|
||||
ftype denom;
|
||||
ftype data[degree + 1];
|
||||
};
|
||||
|
||||
template <class ftype>
|
||||
struct tagPolyE
|
||||
{
|
||||
inline static ftype polye() { return (ftype)1E-10; }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline float tagPolyE<float>::polye() { return 1e-6f; }
|
||||
|
||||
template <class ftype>
|
||||
inline ftype polye() { return tagPolyE<ftype>::polye(); }
|
||||
|
||||
// Don't use this macro; use AZStd::max instead. This is only here to make the template const arguments below readable
|
||||
// and because Visual Studio 2013 doesn't have a const_expr version of std::max
|
||||
#define deprecated_degmax(degree1, degree2) (((degree1) > (degree2)) ? (degree1) : (degree2))
|
||||
|
||||
template<class ftype, int degree>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree> operator+(const polynomial_tpl<ftype, degree>& pn, ftype op)
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res = pn;
|
||||
res.data[0] += op * res.denom;
|
||||
return res;
|
||||
}
|
||||
template<class ftype, int degree>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree> operator-(const polynomial_tpl<ftype, degree>& pn, ftype op)
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res = pn;
|
||||
res.data[0] -= op * res.denom;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class ftype, int degree>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree> operator+(ftype op, const polynomial_tpl<ftype, degree>& pn)
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res = pn;
|
||||
res.data[0] += op * res.denom;
|
||||
return res;
|
||||
}
|
||||
template<class ftype, int degree>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree> operator-(ftype op, const polynomial_tpl<ftype, degree>& pn)
|
||||
{
|
||||
polynomial_tpl<ftype, degree> res = pn;
|
||||
res.data[0] -= op * res.denom;
|
||||
for (int i = 0; i <= degree; i++)
|
||||
{
|
||||
res.data[i] = -res.data[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
template<class ftype, int degree>
|
||||
polynomial_tpl<ftype, degree * 2> AZ_FORCE_INLINE psqr(const polynomial_tpl<ftype, degree>& op) { return op * op; }
|
||||
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, deprecated_degmax(degree1, degree2)> operator+(const polynomial_tpl<ftype, degree1>& op1, const polynomial_tpl<ftype, degree2>& op2)
|
||||
{
|
||||
polynomial_tpl<ftype, deprecated_degmax(degree1, degree2)> res;
|
||||
int i;
|
||||
for (i = 0; i <= min(degree1, degree2); i++)
|
||||
{
|
||||
res.data[i] = op1.data[i] * op2.denom + op2.data[i] * op1.denom;
|
||||
}
|
||||
for (; i <= degree1; i++)
|
||||
{
|
||||
res.data[i] = op1.data[i] * op2.denom;
|
||||
}
|
||||
for (; i <= degree2; i++)
|
||||
{
|
||||
res.data[i] = op2.data[i] * op1.denom;
|
||||
}
|
||||
res.denom = op1.denom * op2.denom;
|
||||
return res;
|
||||
}
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, deprecated_degmax(degree1, degree2)> operator-(const polynomial_tpl<ftype, degree1>& op1, const polynomial_tpl<ftype, degree2>& op2)
|
||||
{
|
||||
polynomial_tpl<ftype, deprecated_degmax(degree1, degree2)> res;
|
||||
int i;
|
||||
for (i = 0; i <= min(degree1, degree2); i++)
|
||||
{
|
||||
res.data[i] = op1.data[i] * op2.denom - op2.data[i] * op1.denom;
|
||||
}
|
||||
for (; i <= degree1; i++)
|
||||
{
|
||||
res.data[i] = op1.data[i] * op2.denom;
|
||||
}
|
||||
for (; i <= degree2; i++)
|
||||
{
|
||||
res.data[i] = op2.data[i] * op1.denom;
|
||||
}
|
||||
res.denom = op1.denom * op2.denom;
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree1>& operator+=(polynomial_tpl<ftype, degree1>& op1, const polynomial_tpl<ftype, degree2>& op2)
|
||||
{
|
||||
for (int i = 0; i < min(degree1, degree2); i++)
|
||||
{
|
||||
op1.data[i] = op1.data[i] * op2.denom + op2.data[i] * op1.denom;
|
||||
}
|
||||
op1.denom *= op2.denom;
|
||||
return op1;
|
||||
}
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree1>& operator-=(polynomial_tpl<ftype, degree1>& op1, const polynomial_tpl<ftype, degree2>& op2)
|
||||
{
|
||||
for (int i = 0; i < min(degree1, degree2); i++)
|
||||
{
|
||||
op1.data[i] = op1.data[i] * op2.denom - op2.data[i] * op1.denom;
|
||||
}
|
||||
op1.denom *= op2.denom;
|
||||
return op1;
|
||||
}
|
||||
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree1 + degree2> operator*(const polynomial_tpl<ftype, degree1>& op1, const polynomial_tpl<ftype, degree2>& op2)
|
||||
{
|
||||
polynomial_tpl<ftype, degree1 + degree2> res;
|
||||
res.zero();
|
||||
int j;
|
||||
switch (degree1)
|
||||
{
|
||||
case 8:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[8 + j] += op1.data[8] * op2.data[j];
|
||||
}
|
||||
case 7:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[7 + j] += op1.data[7] * op2.data[j];
|
||||
}
|
||||
case 6:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[6 + j] += op1.data[6] * op2.data[j];
|
||||
}
|
||||
case 5:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[5 + j] += op1.data[5] * op2.data[j];
|
||||
}
|
||||
case 4:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[4 + j] += op1.data[4] * op2.data[j];
|
||||
}
|
||||
case 3:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[3 + j] += op1.data[3] * op2.data[j];
|
||||
}
|
||||
case 2:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[2 + j] += op1.data[2] * op2.data[j];
|
||||
}
|
||||
case 1:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[1 + j] += op1.data[1] * op2.data[j];
|
||||
}
|
||||
case 0:
|
||||
for (j = 0; j <= degree2; j++)
|
||||
{
|
||||
res.data[0 + j] += op1.data[0] * op2.data[j];
|
||||
}
|
||||
}
|
||||
res.denom = op1.denom * op2.denom;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <class ftype>
|
||||
AZ_FORCE_INLINE void polynomial_divide(const polynomial_tpl<ftype, 8>& num, const polynomial_tpl<ftype, 8>& den, polynomial_tpl<ftype, 8>& quot,
|
||||
polynomial_tpl<ftype, 8>& rem, int degree1, int degree2)
|
||||
{
|
||||
int i, j, k, l;
|
||||
ftype maxel;
|
||||
for (i = 0; i <= degree1; i++)
|
||||
{
|
||||
rem.data[i] = num.data[i];
|
||||
}
|
||||
for (i = 0; i <= degree1 - degree2; i++)
|
||||
{
|
||||
quot.data[i] = 0;
|
||||
}
|
||||
for (i = 1, maxel = fabs_tpl(num.data[0]); i <= degree1; i++)
|
||||
{
|
||||
maxel = max(maxel, num.data[i]);
|
||||
}
|
||||
for (maxel *= polye<ftype>(); degree1 >= 0 && fabs_tpl(num.data[degree1]) < maxel; degree1--)
|
||||
{
|
||||
;
|
||||
}
|
||||
for (i = 1, maxel = fabs_tpl(den.data[0]); i <= degree2; i++)
|
||||
{
|
||||
maxel = max(maxel, den.data[i]);
|
||||
}
|
||||
for (maxel *= polye<ftype>(); degree2 >= 0 && fabs_tpl(den.data[degree2]) < maxel; degree2--)
|
||||
{
|
||||
;
|
||||
}
|
||||
rem.denom = num.denom;
|
||||
quot.denom = (ftype)1;
|
||||
if (degree1 < 0 || degree2 < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (k = degree1 - degree2, l = degree1; l >= degree2; l--, k--)
|
||||
{
|
||||
quot.data[k] = rem.data[l] * den.denom;
|
||||
quot.denom *= den.data[degree2];
|
||||
for (i = degree1 - degree2; i > k; i--)
|
||||
{
|
||||
quot.data[i] *= den.data[degree2];
|
||||
}
|
||||
for (i = degree2 - 1, j = l - 1; i >= 0; i--, j--)
|
||||
{
|
||||
rem.data[j] = rem.data[j] * den.data[degree2] - den.data[i] * rem.data[l];
|
||||
}
|
||||
for (; j >= 0; j--)
|
||||
{
|
||||
rem.data[j] *= den.data[degree2];
|
||||
}
|
||||
rem.denom *= den.data[degree2];
|
||||
}
|
||||
}
|
||||
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree1 - degree2> operator/(const polynomial_tpl<ftype, degree1>& num, const polynomial_tpl<ftype, degree2>& den)
|
||||
{
|
||||
polynomial_tpl<ftype, degree1 - degree2> quot;
|
||||
polynomial_tpl<ftype, degree1> rem;
|
||||
polynomial_divide((polynomial_tpl<ftype, 8>&)num, (polynomial_tpl<ftype, 8>&)den, (polynomial_tpl<ftype, 8>&)quot,
|
||||
(polynomial_tpl<ftype, 8>&)rem, degree1, degree2);
|
||||
return quot;
|
||||
}
|
||||
template <class ftype, int degree1, int degree2>
|
||||
AZ_FORCE_INLINE polynomial_tpl<ftype, degree2 - 1> operator%(const polynomial_tpl<ftype, degree1>& num, const polynomial_tpl<ftype, degree2>& den)
|
||||
{
|
||||
polynomial_tpl<ftype, degree1 - degree2> quot;
|
||||
polynomial_tpl<ftype, degree1> rem;
|
||||
polynomial_divide((polynomial_tpl<ftype, 8>&)num, (polynomial_tpl<ftype, 8>&)den, (polynomial_tpl<ftype, 8>&)quot,
|
||||
(polynomial_tpl<ftype, 8>&)rem, degree1, degree2);
|
||||
return (polynomial_tpl<ftype, degree2 - 1>&)rem;
|
||||
}
|
||||
|
||||
template <class ftype, int degree>
|
||||
AZ_FORCE_INLINE void polynomial_tpl<ftype, degree>::calc_deriviative(polynomial_tpl<ftype, degree>& deriv, int curdegree) const
|
||||
{
|
||||
for (int i = 0; i < curdegree; i++)
|
||||
{
|
||||
deriv.data[i] = data[i + 1] * (i + 1);
|
||||
}
|
||||
deriv.denom = denom;
|
||||
}
|
||||
|
||||
template<typename to_t, typename from_t>
|
||||
to_t* convert_type(from_t* input)
|
||||
{
|
||||
typedef union
|
||||
{
|
||||
to_t* to;
|
||||
from_t* from;
|
||||
} convert_union;
|
||||
convert_union u;
|
||||
u.from = input;
|
||||
return u.to;
|
||||
}
|
||||
|
||||
template <class ftype, int degree>
|
||||
AZ_FORCE_INLINE int polynomial_tpl<ftype, degree>::nroots(ftype start, ftype end) const
|
||||
{
|
||||
polynomial_tpl<ftype, degree> f[degree + 1];
|
||||
int i, j, sg_a, sg_b;
|
||||
ftype val, prevval;
|
||||
|
||||
calc_deriviative(f[0]);
|
||||
polynomial_divide(*convert_type<polynomial_tpl<ftype, 8> >(this), *convert_type< polynomial_tpl<ftype, 8> >(&f[0]), *convert_type<polynomial_tpl<ftype, 8> >(&f[degree]),
|
||||
*convert_type<polynomial_tpl<ftype, 8> >(&f[1]), degree, degree - 1);
|
||||
f[1].denom = -f[1].denom;
|
||||
for (i = 2; i < degree; i++)
|
||||
{
|
||||
polynomial_divide(*convert_type<polynomial_tpl<ftype, 8> >(&f[i - 2]), *convert_type<polynomial_tpl<ftype, 8> >(&f[i - 1]), *convert_type<polynomial_tpl<ftype, 8> >(&f[degree]),
|
||||
*convert_type<polynomial_tpl<ftype, 8> >(&f[i]), degree + 1 - i, degree - i);
|
||||
f[i].denom = -f[i].denom;
|
||||
if (fabs_tpl(f[i].denom) > (ftype)1E10)
|
||||
{
|
||||
for (j = 0; j <= degree - 1 - i; j++)
|
||||
{
|
||||
f[i].data[j] *= (ftype)1E-10;
|
||||
}
|
||||
f[i].denom *= (ftype)1E-10;
|
||||
}
|
||||
}
|
||||
|
||||
prevval = eval(start) * denom;
|
||||
for (i = sg_a = 0; i < degree; i++, prevval = val)
|
||||
{
|
||||
val = f[i].eval(start, degree - 1 - i) * f[i].denom;
|
||||
sg_a += isneg(val * prevval);
|
||||
}
|
||||
|
||||
prevval = eval(end) * denom;
|
||||
for (i = sg_b = 0; i < degree; i++, prevval = val)
|
||||
{
|
||||
val = f[i].eval(end, degree - 1 - i) * f[i].denom;
|
||||
sg_b += isneg(val * prevval);
|
||||
}
|
||||
|
||||
return fabs_tpl(sg_a - sg_b);
|
||||
}
|
||||
|
||||
template<class ftype>
|
||||
AZ_FORCE_INLINE ftype cubert_tpl(ftype x) { return fabs_tpl(x) > (ftype)1E-20 ? exp_tpl(log_tpl(fabs_tpl(x)) * (ftype)(1.0 / 3)) * sgnnz(x) : x; }
|
||||
template<class ftype>
|
||||
AZ_FORCE_INLINE ftype pow_tpl(ftype x, ftype pow) { return fabs_tpl(x) > (ftype)1E-20 ? exp_tpl(log_tpl(fabs_tpl(x)) * pow) * sgnnz(x) : x; }
|
||||
template<class ftype>
|
||||
AZ_FORCE_INLINE void swap(ftype* ptr, int i, int j) { ftype t = ptr[i]; ptr[i] = ptr[j]; ptr[j] = t; }
|
||||
|
||||
template <class ftype, int maxdegree>
|
||||
int polynomial_tpl<ftype, maxdegree>::findroots(ftype start, ftype end, ftype* proots, [[maybe_unused]] int nIters, int degree, bool noDegreeCheck) const
|
||||
{
|
||||
AZ_UNUSED(nIters);
|
||||
int i, j, nRoots = 0;
|
||||
ftype maxel;
|
||||
if (!noDegreeCheck)
|
||||
{
|
||||
for (i = 1, maxel = fabs_tpl(data[0]); i <= degree; i++)
|
||||
{
|
||||
maxel = max(maxel, data[i]);
|
||||
}
|
||||
for (maxel *= polye<ftype>(); degree > 0 && fabs_tpl(data[degree]) <= maxel; degree--)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (maxdegree >= 1)
|
||||
{
|
||||
if (degree == 1)
|
||||
{
|
||||
proots[0] = data[0] / data[1];
|
||||
nRoots = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (maxdegree >= 2)
|
||||
{
|
||||
if (degree == 2)
|
||||
{
|
||||
ftype a, b, c, d, bound[2], sg;
|
||||
|
||||
a = data[2];
|
||||
b = data[1];
|
||||
c = data[0];
|
||||
d = aznumeric_cast<ftype>(sgnnz(a));
|
||||
a *= d;
|
||||
b *= d;
|
||||
c *= d;
|
||||
d = b * b - a * c * 4;
|
||||
bound[0] = start * a * 2 + b;
|
||||
bound[1] = end * a * 2 + b;
|
||||
sg = aznumeric_cast<ftype>((sgnnz(bound[0] * bound[1]) + 1) >> 1);
|
||||
bound[0] *= bound[0];
|
||||
bound[1] *= bound[1];
|
||||
bound[isneg(fabs_tpl(bound[1]) - fabs_tpl(bound[0]))] *= sg;
|
||||
|
||||
if (isnonneg(d) & inrange(d, bound[0], bound[1]))
|
||||
{
|
||||
d = sqrt_tpl(d);
|
||||
a = (ftype)0.5 / a;
|
||||
proots[nRoots] = (-b - d) * a;
|
||||
nRoots += inrange(proots[nRoots], start, end);
|
||||
proots[nRoots] = (-b + d) * a;
|
||||
nRoots += inrange(proots[nRoots], start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (maxdegree >= 3)
|
||||
{
|
||||
if (degree == 3)
|
||||
{
|
||||
ftype t, a, b, c, a3, p, q, Q, Qr, Ar, Ai, phi;
|
||||
|
||||
t = (ftype)1.0 / data[3];
|
||||
a = data[2] * t;
|
||||
b = data[1] * t;
|
||||
c = data[0] * t;
|
||||
a3 = a * (ftype)(1.0 / 3);
|
||||
p = b - a * a3;
|
||||
q = (a3 * b - c) * (ftype)0.5 - cube(a3);
|
||||
Q = cube(p * (ftype)(1.0 / 3)) + q * q;
|
||||
Qr = sqrt_tpl(fabs_tpl(Q));
|
||||
|
||||
if (Q > 0)
|
||||
{
|
||||
proots[0] = cubert_tpl(q + Qr) + cubert_tpl(q - Qr) - a3;
|
||||
nRoots = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
phi = atan2_tpl(Qr, q) * (ftype)(1.0 / 3);
|
||||
t = pow_tpl(Qr * Qr + q * q, (ftype)(1.0 / 6));
|
||||
Ar = t * cos_tpl(phi);
|
||||
Ai = t * sin_tpl(phi);
|
||||
proots[0] = 2 * Ar - a3;
|
||||
proots[1] = aznumeric_cast<ftype>(-Ar + Ai * sqrt3 - a3);
|
||||
proots[2] = aznumeric_cast<ftype>(-Ar - Ai * sqrt3 - a3);
|
||||
i = idxmax3(proots);
|
||||
swap(proots, i, 2);
|
||||
i = isneg(proots[0] - proots[1]);
|
||||
swap(proots, i, 1);
|
||||
nRoots = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (maxdegree >= 4)
|
||||
{
|
||||
if (degree == 4)
|
||||
{
|
||||
ftype t, a3, a2, a1, a0, y, R, D, E, subroots[3];
|
||||
const ftype e = (ftype)1E-9;
|
||||
|
||||
t = (ftype)1.0 / data[4];
|
||||
a3 = data[3] * t;
|
||||
a2 = data[2] * t;
|
||||
a1 = data[1] * t;
|
||||
a0 = data[0] * t;
|
||||
polynomial_tpl<ftype, 3> p3aux;
|
||||
ftype kp3aux[] = { 1, -a2, a1 * a3 - 4 * a0, 4 * a2 * a0 - a1 * a1 - a3 * a3 * a0 };
|
||||
p3aux.set(kp3aux);
|
||||
if (!p3aux.findroots((ftype)-1E20, (ftype)1E20, subroots))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
R = a3 * a3 * (ftype)0.25 - a2 + (y = subroots[0]);
|
||||
|
||||
if (R > -e)
|
||||
{
|
||||
if (R < e)
|
||||
{
|
||||
D = E = a3 * a3 * (ftype)(3.0 / 4) - 2 * a2;
|
||||
t = y * y - 4 * a0;
|
||||
if (t < -e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
t = 2 * sqrt_tpl(max((ftype)0, t));
|
||||
}
|
||||
else
|
||||
{
|
||||
R = sqrt_tpl(max((ftype)0, R));
|
||||
D = E = a3 * a3 * (ftype)(3.0 / 4) - R * R - 2 * a2;
|
||||
t = (4 * a3 * a2 - 8 * a1 - a3 * a3 * a3) / R * (ftype)0.25;
|
||||
}
|
||||
if (D + t > -e)
|
||||
{
|
||||
D = sqrt_tpl(max((ftype)0, D + t));
|
||||
proots[nRoots++] = a3 * (ftype)-0.25 + (R - D) * (ftype)0.5;
|
||||
proots[nRoots++] = a3 * (ftype)-0.25 + (R + D) * (ftype)0.5;
|
||||
}
|
||||
if (E - t > -e)
|
||||
{
|
||||
E = sqrt_tpl(max((ftype)0, E - t));
|
||||
proots[nRoots++] = a3 * (ftype)-0.25 - (R + E) * (ftype)0.5;
|
||||
proots[nRoots++] = a3 * (ftype)-0.25 - (R - E) * (ftype)0.5;
|
||||
}
|
||||
if (nRoots == 4)
|
||||
{
|
||||
i = idxmax3(proots);
|
||||
if (proots[3] < proots[i])
|
||||
{
|
||||
swap(proots, i, 3);
|
||||
}
|
||||
i = idxmax3(proots);
|
||||
swap(proots, i, 2);
|
||||
i = isneg(proots[0] - proots[1]);
|
||||
swap(proots, i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (maxdegree > 4)
|
||||
{
|
||||
if (degree > 4)
|
||||
{
|
||||
ftype roots[maxdegree + 1], prevroot, val, prevval[2], curval, bound[2], middle;
|
||||
polynomial_tpl<ftype, maxdegree> deriv;
|
||||
int nExtremes, iter, iBound;
|
||||
calc_deriviative(deriv);
|
||||
|
||||
// find a subset of deriviative extremes between start and end
|
||||
for (nExtremes = deriv.findroots(start, end, roots + 1, nIters, degree - 1) + 1; nExtremes > 1 && roots[nExtremes - 1] > end; nExtremes--)
|
||||
{
|
||||
;
|
||||
}
|
||||
for (i = 1; i < nExtremes && roots[i] < start; i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
roots[i - 1] = start;
|
||||
PREFAST_ASSUME(nExtremes < maxdegree + 1);
|
||||
roots[nExtremes++] = end;
|
||||
|
||||
for (prevroot = start, prevval[0] = eval(start, degree), nRoots = 0; i < nExtremes; prevval[0] = val, prevroot = roots[i++])
|
||||
{
|
||||
val = eval(roots[i], degree);
|
||||
if (val * prevval[0] < 0)
|
||||
{
|
||||
// we have exactly one root between prevroot and roots[i]
|
||||
bound[0] = prevroot;
|
||||
bound[1] = roots[i];
|
||||
iter = 0;
|
||||
do
|
||||
{
|
||||
middle = (bound[0] + bound[1]) * (ftype)0.5;
|
||||
curval = eval(middle, degree);
|
||||
iBound = isneg(prevval[0] * curval);
|
||||
bound[iBound] = middle;
|
||||
prevval[iBound] = curval;
|
||||
} while (++iter < nIters);
|
||||
proots[nRoots++] = middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nRoots && proots[i] < start; i++)
|
||||
{
|
||||
;
|
||||
}
|
||||
for (; nRoots > i&& proots[nRoots - 1] > end; nRoots--)
|
||||
{
|
||||
;
|
||||
}
|
||||
for (j = i; j < nRoots; j++)
|
||||
{
|
||||
proots[j - i] = proots[j];
|
||||
}
|
||||
|
||||
return nRoots - i;
|
||||
}
|
||||
} // namespace polynomial_tpl_IMPL
|
||||
template<class ftype, int degree>
|
||||
using polynomial_tpl = polynomial_tpl_IMPL::polynomial_tpl<ftype, degree>;
|
||||
|
||||
typedef polynomial_tpl<real, 3> P3;
|
||||
typedef polynomial_tpl<real, 2> P2;
|
||||
typedef polynomial_tpl<real, 1> P1;
|
||||
typedef polynomial_tpl<float, 3> P3f;
|
||||
typedef polynomial_tpl<float, 2> P2f;
|
||||
typedef polynomial_tpl<float, 1> P1f;
|
||||
} // namespace LegacyCryPhysicsUtils
|
||||
@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "DeepFilterProxyModel.h"
|
||||
#include <QPalette>
|
||||
|
||||
DeepFilterProxyModel::DeepFilterProxyModel(QObject* parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void DeepFilterProxyModel::setFilterString(const QString& filter)
|
||||
{
|
||||
m_filter = filter;
|
||||
m_filterParts = m_filter.split(' ', Qt::SkipEmptyParts);
|
||||
m_acceptCache.clear();
|
||||
}
|
||||
|
||||
void DeepFilterProxyModel::invalidate()
|
||||
{
|
||||
QSortFilterProxyModel::invalidate();
|
||||
m_acceptCache.clear();
|
||||
}
|
||||
|
||||
QVariant DeepFilterProxyModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::ForegroundRole)
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
if (matchFilter(sourceIndex.row(), sourceIndex.parent()))
|
||||
{
|
||||
return QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QPalette().color(QPalette::Disabled, QPalette::Text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeepFilterProxyModel::setFilterWildcard(const QString& pattern)
|
||||
{
|
||||
m_acceptCache.clear();
|
||||
QSortFilterProxyModel::setFilterWildcard(pattern);
|
||||
}
|
||||
|
||||
bool DeepFilterProxyModel::matchFilter(int sourceRow, const QModelIndex& sourceParent) const
|
||||
{
|
||||
int columnCount = sourceModel()->columnCount(sourceParent);
|
||||
for (int i = 0; i < m_filterParts.size(); ++i)
|
||||
{
|
||||
bool atLeastOneContains = false;
|
||||
for (int j = 0; j < columnCount; ++j)
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(sourceRow, j, sourceParent);
|
||||
QVariant data = sourceModel()->data(index, Qt::DisplayRole);
|
||||
QString str(data.toString());
|
||||
if (str.isEmpty())
|
||||
{
|
||||
if (m_filterParts.empty())
|
||||
{
|
||||
atLeastOneContains = true;
|
||||
}
|
||||
}
|
||||
else if (str.contains(m_filterParts[i], Qt::CaseInsensitive))
|
||||
{
|
||||
atLeastOneContains = true;
|
||||
}
|
||||
}
|
||||
if (!atLeastOneContains)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeepFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
|
||||
{
|
||||
if (matchFilter(sourceRow, sourceParent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasAcceptedChildrenCached(sourceRow, sourceParent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeepFilterProxyModel::hasAcceptedChildrenCached(int sourceRow, const QModelIndex& sourceParent) const
|
||||
{
|
||||
std::pair<QModelIndex, int> indexId = std::make_pair(sourceParent, sourceRow);
|
||||
TAcceptCache::iterator it = m_acceptCache.find(indexId);
|
||||
if (it == m_acceptCache.end())
|
||||
{
|
||||
bool result = hasAcceptedChildren(sourceRow, sourceParent);
|
||||
m_acceptCache[indexId] = result;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool DeepFilterProxyModel::hasAcceptedChildren(int sourceRow, const QModelIndex& sourceParent) const
|
||||
{
|
||||
QModelIndex item = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
if (!item.isValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int childCount = item.model()->rowCount(item);
|
||||
if (childCount == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < childCount; ++i)
|
||||
{
|
||||
if (filterAcceptsRow(i, item))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex DeepFilterProxyModel::findFirstMatchingIndex(const QModelIndex& root)
|
||||
{
|
||||
int rowCount = this->rowCount(root);
|
||||
for (int i = 0; i < rowCount; ++i)
|
||||
{
|
||||
QModelIndex index = this->index(i, 0, root);
|
||||
if (!index.isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
if (!sourceIndex.isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (matchFilter(sourceIndex.row(), sourceIndex.parent()))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
QModelIndex child = findFirstMatchingIndex(index);
|
||||
if (child.isValid())
|
||||
{
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITORCOMMON_DEEPFILTERPROXYMODEL_H
|
||||
#define CRYINCLUDE_EDITORCOMMON_DEEPFILTERPROXYMODEL_H
|
||||
#pragma once
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QModelIndex>
|
||||
#include <QStringList>
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
class EDITOR_COMMON_API DeepFilterProxyModel
|
||||
: public QSortFilterProxyModel
|
||||
{
|
||||
public:
|
||||
DeepFilterProxyModel(QObject* parent);
|
||||
|
||||
void setFilterString(const QString& filter);
|
||||
void invalidate();
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
void setFilterWildcard(const QString& pattern);
|
||||
|
||||
bool matchFilter(int source_row, const QModelIndex& source_parent) const;
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override;
|
||||
bool hasAcceptedChildrenCached(int source_row, const QModelIndex& source_parent) const;
|
||||
bool hasAcceptedChildren(int source_row, const QModelIndex& source_parent) const;
|
||||
|
||||
QModelIndex findFirstMatchingIndex(const QModelIndex& root);
|
||||
|
||||
private:
|
||||
QString m_filter;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QStringList m_filterParts;
|
||||
typedef std::map<std::pair<QModelIndex, int>, bool> TAcceptCache;
|
||||
mutable TAcceptCache m_acceptCache;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITORCOMMON_DEEPFILTERPROXYMODEL_H
|
||||
@ -1,9 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../Editor/Objects/DisplayContextShared.inl"
|
||||
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "Ruler.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPalette>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
|
||||
namespace DrawingPrimitives
|
||||
{
|
||||
enum
|
||||
{
|
||||
RULER_MIN_PIXELS_PER_TICK = 3,
|
||||
};
|
||||
|
||||
std::vector<STick> CalculateTicks(uint size, Range visibleRange, Range rulerRange, int* pRulerPrecision, Range* pScreenRulerRange)
|
||||
{
|
||||
std::vector<STick> ticks;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
if (pRulerPrecision)
|
||||
{
|
||||
*pRulerPrecision = 0;
|
||||
}
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
const float pixelsPerUnit = visibleRange.Length() > 0.0f ? (float)size / visibleRange.Length() : 1.0f;
|
||||
|
||||
const float startTime = rulerRange.start;
|
||||
const float endTime = rulerRange.end;
|
||||
const float totalDuration = endTime - startTime;
|
||||
|
||||
const float ticksMinPower = log10f(RULER_MIN_PIXELS_PER_TICK);
|
||||
const float ticksPowerDelta = ticksMinPower - log10f(pixelsPerUnit);
|
||||
|
||||
const int digitsAfterPoint = AZStd::max(-int(ceil(ticksPowerDelta)) - 1, 0);
|
||||
if (pRulerPrecision)
|
||||
{
|
||||
*pRulerPrecision = digitsAfterPoint;
|
||||
}
|
||||
|
||||
const float scaleStep = powf(10.0f, ceil(ticksPowerDelta));
|
||||
const float scaleStepPixels = scaleStep * pixelsPerUnit;
|
||||
const int numMarkers = int(totalDuration / scaleStep) + 1;
|
||||
|
||||
const float startTimeRound = int(startTime / scaleStep) * scaleStep;
|
||||
const int startOffsetMod = int(startTime / scaleStep) % 10;
|
||||
const int scaleOffsetPixels = aznumeric_cast<int>((startTime - startTimeRound) * pixelsPerUnit);
|
||||
|
||||
const int startX = aznumeric_cast<int>((rulerRange.start - visibleRange.start) * pixelsPerUnit);
|
||||
const int endX = aznumeric_cast<int>(startX + (numMarkers - 1) * scaleStepPixels - scaleOffsetPixels);
|
||||
|
||||
if (pScreenRulerRange)
|
||||
{
|
||||
*pScreenRulerRange = Range(aznumeric_cast<float>(startX), aznumeric_cast<float>(endX));
|
||||
}
|
||||
|
||||
const int startLoop = std::max((int)((scaleOffsetPixels - startX) / scaleStepPixels) - 1, 0);
|
||||
const int endLoop = std::min((int)((size + scaleOffsetPixels - startX) / scaleStepPixels) + 1, numMarkers);
|
||||
|
||||
for (int i = startLoop; i < endLoop; ++i)
|
||||
{
|
||||
STick tick;
|
||||
|
||||
const int x = aznumeric_cast<int>(startX + i * scaleStepPixels - scaleOffsetPixels);
|
||||
const float value = startTimeRound + i * scaleStep;
|
||||
|
||||
tick.m_bTenth = (startOffsetMod + i) % 10 != 0;
|
||||
tick.m_position = x;
|
||||
tick.m_value = value;
|
||||
|
||||
ticks.push_back(tick);
|
||||
}
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
QColor Interpolate(const QColor& a, const QColor& b, float k)
|
||||
{
|
||||
float mk = 1.0f - k;
|
||||
return QColor(aznumeric_cast<int>(a.red() * mk + b.red() * k),
|
||||
aznumeric_cast<int>(a.green() * mk + b.green() * k),
|
||||
aznumeric_cast<int>(a.blue() * mk + b.blue() * k),
|
||||
aznumeric_cast<int>(a.alpha() * mk + b.alpha() * k));
|
||||
}
|
||||
|
||||
void DrawTicks(const std::vector<STick>& ticks, QPainter& painter, const QPalette& palette, const STickOptions& options)
|
||||
{
|
||||
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
painter.setPen(QPen(midDark));
|
||||
|
||||
const int height = options.m_rect.height();
|
||||
const int top = options.m_rect.top();
|
||||
|
||||
for (const STick& tick : ticks)
|
||||
{
|
||||
const int x = tick.m_position + options.m_rect.left();
|
||||
|
||||
if (tick.m_bTenth)
|
||||
{
|
||||
painter.drawLine(QPoint(x, top + height - options.m_markHeight / 2), QPoint(x, top + height));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawLine(QPoint(x, top + height - options.m_markHeight), QPoint(x, top + height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTicks(QPainter& painter, const QPalette& palette, const SRulerOptions& options)
|
||||
{
|
||||
const std::vector<STick> ticks = CalculateTicks(options.m_rect.width(), options.m_visibleRange, options.m_rulerRange, nullptr, nullptr);
|
||||
DrawTicks(ticks, painter, palette, options);
|
||||
}
|
||||
|
||||
void DrawRuler(QPainter& painter, const QPalette& palette, const SRulerOptions& options, int* pRulerPrecision)
|
||||
{
|
||||
int rulerPrecision;
|
||||
Range screenRulerRange;
|
||||
const std::vector<STick> ticks = CalculateTicks(options.m_rect.width(), options.m_visibleRange, options.m_rulerRange, &rulerPrecision, &screenRulerRange);
|
||||
|
||||
if (pRulerPrecision)
|
||||
{
|
||||
*pRulerPrecision = rulerPrecision;
|
||||
}
|
||||
|
||||
if (options.m_shadowSize > 0)
|
||||
{
|
||||
QRect shadowRect = QRect(options.m_rect.left(), options.m_rect.height(), options.m_rect.width(), options.m_shadowSize);
|
||||
QLinearGradient upperGradient(shadowRect.left(), shadowRect.top(), shadowRect.left(), shadowRect.bottom());
|
||||
upperGradient.setColorAt(0.0f, QColor(0, 0, 0, 128));
|
||||
upperGradient.setColorAt(1.0f, QColor(0, 0, 0, 0));
|
||||
QBrush upperBrush(upperGradient);
|
||||
painter.fillRect(shadowRect, upperBrush);
|
||||
}
|
||||
|
||||
painter.fillRect(options.m_rect, DrawingPrimitives::Interpolate(palette.color(QPalette::Button), palette.color(QPalette::Midlight), 0.25f));
|
||||
if (options.m_drawBackgroundCallback)
|
||||
{
|
||||
options.m_drawBackgroundCallback();
|
||||
}
|
||||
|
||||
QColor midDark = DrawingPrimitives::Interpolate(palette.color(QPalette::Dark), palette.color(QPalette::Button), 0.5f);
|
||||
painter.setPen(QPen(midDark));
|
||||
|
||||
QFont font;
|
||||
font.setPixelSize(10);
|
||||
painter.setFont(font);
|
||||
|
||||
|
||||
char format[16] = "";
|
||||
azsprintf(format, "%%.%df", rulerPrecision);
|
||||
|
||||
const int height = options.m_rect.height();
|
||||
const int top = options.m_rect.top();
|
||||
|
||||
QString str;
|
||||
for (const STick& tick : ticks)
|
||||
{
|
||||
const int x = tick.m_position + options.m_rect.left();
|
||||
const float value = tick.m_value;
|
||||
|
||||
if (tick.m_bTenth)
|
||||
{
|
||||
painter.drawLine(QPoint(x, top + height - options.m_markHeight / 2), QPoint(x, top + height));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawLine(QPoint(x, top + height - options.m_markHeight), QPoint(x, top + height));
|
||||
painter.setPen(palette.color(QPalette::Disabled, QPalette::Text));
|
||||
str.asprintf(format, value);
|
||||
painter.drawText(QPoint(x + 2, top + height - options.m_markHeight + 1), str);
|
||||
painter.setPen(midDark);
|
||||
}
|
||||
}
|
||||
|
||||
painter.setPen(QPen(palette.color(QPalette::Dark)));
|
||||
painter.drawLine(QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.start), 0), QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.start), options.m_rect.top() + height));
|
||||
painter.drawLine(QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.end), 0), QPoint(aznumeric_cast<int>(options.m_rect.left() + screenRulerRange.end), options.m_rect.top() + height));
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Range.h"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <QRect>
|
||||
|
||||
class QPainter;
|
||||
class QPalette;
|
||||
|
||||
namespace DrawingPrimitives
|
||||
{
|
||||
struct SRulerOptions;
|
||||
typedef std::function<void()> TDrawCallback;
|
||||
|
||||
struct SRulerOptions
|
||||
{
|
||||
QRect m_rect;
|
||||
Range m_visibleRange;
|
||||
Range m_rulerRange;
|
||||
int m_textXOffset;
|
||||
int m_textYOffset;
|
||||
int m_markHeight;
|
||||
int m_shadowSize;
|
||||
|
||||
TDrawCallback m_drawBackgroundCallback;
|
||||
};
|
||||
|
||||
struct STick
|
||||
{
|
||||
bool m_bTenth;
|
||||
int m_position;
|
||||
float m_value;
|
||||
};
|
||||
|
||||
typedef SRulerOptions STickOptions;
|
||||
|
||||
std::vector<STick> CalculateTicks(uint size, Range visibleRange, Range rulerRange, int* pRulerPrecision, Range* pScreenRulerRange);
|
||||
void DrawTicks(const std::vector<STick>& ticks, QPainter& painter, const QPalette& palette, const STickOptions& options);
|
||||
void DrawTicks(QPainter& painter, const QPalette& palette, const STickOptions& options);
|
||||
void DrawRuler(QPainter& painter, const QPalette& palette, const SRulerOptions& options, int* pRulerPrecision);
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "TimeSlider.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPalette>
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
namespace DrawingPrimitives
|
||||
{
|
||||
void DrawTimeSlider(QPainter& painter, const QPalette& palette, const STimeSliderOptions& options)
|
||||
{
|
||||
QString text = QString::number(options.m_time, 'f', options.m_precision + 1);
|
||||
|
||||
QFontMetrics fm(painter.font());
|
||||
const int textWidth = fm.horizontalAdvance(text) + fm.height();
|
||||
const int markerHeight = fm.height();
|
||||
|
||||
const int thumbX = options.m_position;
|
||||
const bool fits = thumbX + textWidth < options.m_rect.right();
|
||||
|
||||
const QRect timeRect(fits ? thumbX : thumbX - textWidth, 3, textWidth, fm.height());
|
||||
painter.fillRect(timeRect.adjusted(fits ? 0 : -1, 0, fits ? 1 : 0, 0), options.m_bHasFocus ? palette.highlight() : palette.shadow());
|
||||
painter.setPen(palette.color(QPalette::HighlightedText));
|
||||
painter.drawText(timeRect.adjusted(fits ? 0 : aznumeric_cast<int>(markerHeight * 0.2f), -1, fits ? aznumeric_cast<int>(-markerHeight * 0.2f) : 0, 0), text, QTextOption(fits ? Qt::AlignRight : Qt::AlignLeft));
|
||||
|
||||
painter.setPen(palette.color(QPalette::Text));
|
||||
painter.drawLine(QPointF(thumbX, 0), QPointF(thumbX, options.m_rect.height()));
|
||||
QPointF points[3] =
|
||||
{
|
||||
QPointF(thumbX, markerHeight),
|
||||
QPointF(thumbX - markerHeight * 0.66f, 0),
|
||||
QPointF(thumbX + markerHeight * 0.66f, 0)
|
||||
};
|
||||
|
||||
painter.setBrush(palette.base());
|
||||
painter.setPen(palette.color(QPalette::Text));
|
||||
painter.drawPolygon(points, 3);
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Range.h"
|
||||
|
||||
#include <QRect>
|
||||
|
||||
class QPainter;
|
||||
class QPalette;
|
||||
|
||||
namespace DrawingPrimitives
|
||||
{
|
||||
struct STimeSliderOptions
|
||||
{
|
||||
QRect m_rect;
|
||||
int m_precision;
|
||||
int m_position;
|
||||
float m_time;
|
||||
bool m_bHasFocus;
|
||||
};
|
||||
|
||||
void DrawTimeSlider(QPainter& painter, const QPalette& palette, const STimeSliderOptions& options);
|
||||
}
|
||||
Binary file not shown.
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3e60156229cc8677e0294d297486f04bd78867ef4e0922b35444c8b45f78584d
|
||||
size 1090
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd29a16a1d1d9a363e4b154d51910c2cba2787fbbe1360cfd107b393053d2e49
|
||||
size 1226
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:244005cde119238bbfc2815f36a343c6135c3233d0b72a5c97a6080604568e8f
|
||||
size 1160
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:33176a8ea6b0798adf1114fdbea4b0f5c708f40c3d48a047b1cb0fa6ebcbbded
|
||||
size 1181
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c122557745cc377768491ce59c5b5b17e54671aa59f7f87101766aa61758959e
|
||||
size 939
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3c2a360a56a37bfae2bea16b495f5b6ee482caa28d0949e8eadea48fdaae654f
|
||||
size 845
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eb0f43228bdb5246ea3bfde0726f07e0df0468279610ba4c801b21e264b33123
|
||||
size 765
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:97a2e879222323bc70787efbe2cbc1c47bbabb7b10df8465857e600a9084abb2
|
||||
size 795
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58e8476b7bec1ed8eddfde3d5228f58fcfba11329318f5dfef3d98eb99f3a897
|
||||
size 1113
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a7847e8b7f3dd76395d893888916e4bd97ddf3f678d37d19836da04c2923791e
|
||||
size 871
|
||||
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:470266956c6911690299f29539c400122ae707f88d9b6ba3516faf196a8fd571
|
||||
size 877
|
||||
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
|
||||
#include <afxwin.h>
|
||||
#include <vector>
|
||||
|
||||
#include "QtViewPane.h"
|
||||
|
||||
#include "Include/IViewPane.h"
|
||||
#include "Util/RefCountBase.h"
|
||||
#include "QtWinMigrate/qwinwidget.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
#include <QApplication>
|
||||
#include <QCloseEvent>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "QtUtil.h"
|
||||
|
||||
// ugly dependencies:
|
||||
#include "Functor.h"
|
||||
class CXmlArchive;
|
||||
#include <IRenderer.h>
|
||||
#include "Util/PathUtil.h"
|
||||
// ^^^
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by EditorCommon.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#define _APS_NEXT_RESOURCE_VALUE 1000
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 1000
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#endif
|
||||
#endif
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EditorCommonAPI.h"
|
||||
#include "IEditor.h"
|
||||
|
||||
|
||||
#include <WinWidget/WinWidgetManager.h>
|
||||
#include <Core/QtEditorApplication.h>
|
||||
#include <QWidget>
|
||||
|
||||
namespace WinWidget
|
||||
{
|
||||
template<class TWidget>
|
||||
bool RegisterWinWidget()
|
||||
{
|
||||
static QWidget* winWidget {nullptr}; // Must declare outside of lambda
|
||||
|
||||
WinWidget::WinWidgetManager::WinWidgetCreateCall createCall = []() -> QWidget*
|
||||
{
|
||||
if (!winWidget)
|
||||
{
|
||||
winWidget = new QWidget(GetIEditor()->GetEditorMainWindow());
|
||||
}
|
||||
|
||||
// Ensure only one instance of each window type exists
|
||||
QList<TWidget*> existingWidgets = winWidget->findChildren<TWidget*>();
|
||||
if (existingWidgets.size() > 0) // Note that the list should contain 0 or 1 entries
|
||||
{
|
||||
if (existingWidgets.first()->isVisible())
|
||||
{
|
||||
return nullptr; // TWidget type already in use - continue using it and don't create another
|
||||
}
|
||||
delete existingWidgets.first(); // Closed TWidget - remove
|
||||
}
|
||||
|
||||
TWidget* createWidget = new TWidget(winWidget);
|
||||
|
||||
createWidget->Display();
|
||||
return winWidget;
|
||||
};
|
||||
|
||||
return GetIEditor()->GetWinWidgetManager()->RegisterWinWidget(TWidget::GetWWId(), createCall);
|
||||
}
|
||||
|
||||
template<class TWidget>
|
||||
void UnregisterWinWidget()
|
||||
{
|
||||
GetIEditor()->GetWinWidgetManager()->UnregisterWinWidget(TWidget::GetWWId());
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <WinWidget/WinWidgetManager.h>
|
||||
|
||||
namespace WinWidget
|
||||
{
|
||||
WinWidgetManager::WinWidgetManager()
|
||||
: m_createCalls(size_t(WinWidgetId::NUM_WIN_WIDGET_IDS) + 1)
|
||||
{
|
||||
}
|
||||
|
||||
size_t WinWidgetManager::GetIndexForId(WinWidgetId thisId) const
|
||||
{
|
||||
size_t thisIndex = static_cast<size_t>(thisId);
|
||||
if (thisIndex >= m_createCalls.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return thisIndex;
|
||||
}
|
||||
|
||||
WinWidgetManager::WinWidgetCreateCall WinWidgetManager::GetCreateCall(WinWidgetId thisId) const
|
||||
{
|
||||
size_t thisIndex = GetIndexForId(thisId);
|
||||
if (!thisIndex)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return m_createCalls[thisIndex];
|
||||
}
|
||||
|
||||
bool WinWidgetManager::RegisterWinWidget(WinWidgetId thisId, WinWidgetCreateCall createCall)
|
||||
{
|
||||
size_t thisIndex = GetIndexForId(thisId);
|
||||
if (m_createCalls[thisIndex] != nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_createCalls[thisIndex] = createCall;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinWidgetManager::UnregisterWinWidget(WinWidgetId thisId)
|
||||
{
|
||||
size_t thisIndex = GetIndexForId(thisId);
|
||||
if (m_createCalls[thisIndex] == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_createCalls[thisIndex] = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QWidget* WinWidgetManager::OpenWinWidget(WinWidgetId createId) const
|
||||
{
|
||||
WinWidgetManager::WinWidgetCreateCall createCall = GetCreateCall(createId);
|
||||
if (!createCall)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return createCall();
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WinWidgetId.h>
|
||||
#include "EditorCommonAPI.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace WinWidget
|
||||
{
|
||||
class EDITOR_COMMON_API WinWidgetManager
|
||||
{
|
||||
public:
|
||||
using WinWidgetCreateCall = std::function<QWidget*()>;
|
||||
|
||||
WinWidgetManager();
|
||||
~WinWidgetManager() {}
|
||||
|
||||
bool RegisterWinWidget(WinWidgetId thisId, WinWidgetCreateCall createCall);
|
||||
bool UnregisterWinWidget(WinWidgetId thisId);
|
||||
|
||||
QWidget* OpenWinWidget(WinWidgetId) const;
|
||||
private:
|
||||
WinWidgetCreateCall GetCreateCall(WinWidgetId thisId) const;
|
||||
size_t GetIndexForId(WinWidgetId thisId) const;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::vector<WinWidgetCreateCall> m_createCalls;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE 9, 1
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by FFMPEGPlugin.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@ -1,4 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -1,71 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_P4 ICON "res\\p4.ico"
|
||||
IDI_P4_ERROR ICON "res\\p4_error.ico"
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#define IDI_P4 104
|
||||
#define IDI_P4_ERROR 106
|
||||
#define IDC_ERROR 1004
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 107
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1010
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Generic report class, which contains arbitrary report entries.
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_REPORT_H
|
||||
#define CRYINCLUDE_EDITOR_REPORT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class IReportField
|
||||
{
|
||||
public:
|
||||
virtual ~IReportField() {}
|
||||
|
||||
virtual const char* GetDescription() const = 0;
|
||||
virtual const char* GetText() const = 0;
|
||||
};
|
||||
|
||||
template <typename T, typename G>
|
||||
class CReportField
|
||||
: public IReportField
|
||||
{
|
||||
public:
|
||||
typedef T Object;
|
||||
typedef G TextGetter;
|
||||
|
||||
CReportField(Object& object, const char* description, TextGetter& getter);
|
||||
virtual const char* GetDescription() const;
|
||||
virtual const char* GetText() const;
|
||||
|
||||
private:
|
||||
TextGetter m_getter;
|
||||
string m_text;
|
||||
string m_description;
|
||||
};
|
||||
|
||||
class IReportRecord
|
||||
{
|
||||
public:
|
||||
virtual ~IReportRecord() {}
|
||||
virtual int GetFieldCount() const = 0;
|
||||
virtual const char* GetFieldDescription(int fieldIndex) const = 0;
|
||||
virtual const char* GetFieldText(int fieldIndex) const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CReportRecord
|
||||
: public IReportRecord
|
||||
{
|
||||
public:
|
||||
typedef T Object;
|
||||
|
||||
CReportRecord(Object& object);
|
||||
virtual ~CReportRecord();
|
||||
virtual int GetFieldCount() const;
|
||||
virtual const char* GetFieldDescription(int fieldIndex) const;
|
||||
virtual const char* GetFieldText(int fieldIndex) const;
|
||||
template <typename G>
|
||||
CReportField<Object, G>* AddField(const char* description, G& getter);
|
||||
|
||||
private:
|
||||
Object m_object;
|
||||
typedef std::vector<IReportField*> FieldContainer;
|
||||
FieldContainer m_fields;
|
||||
};
|
||||
|
||||
class CReport
|
||||
{
|
||||
public:
|
||||
~CReport();
|
||||
template <typename T>
|
||||
CReportRecord<T>* AddRecord(T& object);
|
||||
int GetRecordCount() const;
|
||||
IReportRecord* GetRecord(int recordIndex);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
typedef std::vector<IReportRecord*> RecordContainer;
|
||||
RecordContainer m_records;
|
||||
};
|
||||
|
||||
template <typename T, typename G>
|
||||
inline CReportField<T, G>::CReportField(Object& object, const char* description, TextGetter& getter)
|
||||
: m_getter(getter)
|
||||
, m_description(description)
|
||||
{
|
||||
m_text = m_getter(object);
|
||||
}
|
||||
|
||||
template <typename T, typename G>
|
||||
inline const char* CReportField<T, G>::GetDescription() const
|
||||
{
|
||||
return m_description.c_str();
|
||||
}
|
||||
|
||||
template <typename T, typename G>
|
||||
inline const char* CReportField<T, G>::GetText() const
|
||||
{
|
||||
return m_text.c_str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CReportRecord<T>::CReportRecord(Object& object)
|
||||
: m_object(object)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CReportRecord<T>::~CReportRecord()
|
||||
{
|
||||
for (FieldContainer::iterator it = m_fields.begin(); it != m_fields.end(); ++it)
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int CReportRecord<T>::GetFieldCount() const
|
||||
{
|
||||
return m_fields.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const char* CReportRecord<T>::GetFieldDescription(int fieldIndex) const
|
||||
{
|
||||
return m_fields[fieldIndex]->GetDescription();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const char* CReportRecord<T>::GetFieldText(int fieldIndex) const
|
||||
{
|
||||
return m_fields[fieldIndex]->GetText();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename G>
|
||||
inline CReportField<T, G>* CReportRecord<T>::AddField(const char* description, G& getter)
|
||||
{
|
||||
CReportField<Object, G>* field = new CReportField<Object, G>(m_object, description, getter);
|
||||
m_fields.push_back(field);
|
||||
return field;
|
||||
}
|
||||
|
||||
inline CReport::~CReport()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CReportRecord<T>* CReport::AddRecord(T& object)
|
||||
{
|
||||
CReportRecord<T>* record = new CReportRecord<T>(object);
|
||||
m_records.push_back(record);
|
||||
return record;
|
||||
}
|
||||
|
||||
inline int CReport::GetRecordCount() const
|
||||
{
|
||||
return m_records.size();
|
||||
}
|
||||
|
||||
inline IReportRecord* CReport::GetRecord(int recordIndex)
|
||||
{
|
||||
return m_records[recordIndex];
|
||||
}
|
||||
|
||||
inline void CReport::Clear()
|
||||
{
|
||||
for (RecordContainer::iterator it = m_records.begin(); it != m_records.end(); ++it)
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
m_records.clear();
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_REPORT_H
|
||||
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ResizeResolutionDialog.h"
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <ui_ResizeResolutionDialog.h>
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
class ResizeResolutionModel
|
||||
: public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
ResizeResolutionModel(QObject* parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& parent = {}) const override;
|
||||
int columnCount(const QModelIndex& parent = {}) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
int SizeRow(uint32 dwSize) const;
|
||||
|
||||
private:
|
||||
static const int kNumSizes = 6;
|
||||
};
|
||||
|
||||
ResizeResolutionModel::ResizeResolutionModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int ResizeResolutionModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : kNumSizes;
|
||||
}
|
||||
|
||||
int ResizeResolutionModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
}
|
||||
|
||||
QVariant ResizeResolutionModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.column() > 0 || index.row() >= kNumSizes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const int size = 64 * (1 << index.row());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return QStringLiteral("%1x%2").arg(size).arg(size);
|
||||
|
||||
case Qt::UserRole:
|
||||
return size;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int ResizeResolutionModel::SizeRow(uint32 dwSize) const
|
||||
{
|
||||
// not a power of 2?
|
||||
if (dwSize & (dwSize - 1))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
|
||||
for (auto i = dwSize / 64; i > 1; i >>= 1)
|
||||
{
|
||||
++row;
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CResizeResolutionDialog dialog
|
||||
|
||||
|
||||
CResizeResolutionDialog::CResizeResolutionDialog(QWidget* pParent /*=nullptr*/)
|
||||
: QDialog(pParent)
|
||||
, m_model(new ResizeResolutionModel(this))
|
||||
, ui(new Ui::CResizeResolutionDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->m_resolution->setModel(m_model);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
CResizeResolutionDialog::~CResizeResolutionDialog()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CResizeResolutionDialog::SetSize(uint32 dwSize)
|
||||
{
|
||||
ui->m_resolution->setCurrentIndex(m_model->SizeRow(dwSize));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
uint32 CResizeResolutionDialog::GetSize()
|
||||
{
|
||||
return ui->m_resolution->itemData(ui->m_resolution->currentIndex()).toInt();
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_RESIZERESOLUTIONDIALOG_H
|
||||
#define CRYINCLUDE_EDITOR_RESIZERESOLUTIONDIALOG_H
|
||||
|
||||
#pragma once
|
||||
// ResizeResolutionDialog.h : header file
|
||||
//
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
namespace Ui {
|
||||
class CResizeResolutionDialog;
|
||||
}
|
||||
|
||||
class ResizeResolutionModel;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CResizeResolutionDialog dialog
|
||||
|
||||
class CResizeResolutionDialog
|
||||
: public QDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CResizeResolutionDialog(QWidget* pParent = nullptr); // standard constructor
|
||||
~CResizeResolutionDialog();
|
||||
|
||||
void SetSize(uint32 dwSize);
|
||||
uint32 GetSize();
|
||||
|
||||
private:
|
||||
ResizeResolutionModel* m_model;
|
||||
QScopedPointer<Ui::CResizeResolutionDialog> ui;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_RESIZERESOLUTIONDIALOG_H
|
||||
@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CResizeResolutionDialog</class>
|
||||
<widget class="QDialog" name="CResizeResolutionDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>96</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select resolution:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_resolution"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::HLine</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Utility classes used by Editor.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Cry_Color.h>
|
||||
|
||||
class QColor;
|
||||
|
||||
QColor ColorLinearToGamma(ColorF col);
|
||||
ColorF ColorGammaToLinear(const QColor& col);
|
||||
QColor ColorToQColor(uint32 color);
|
||||
|
||||
@ -1,455 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
/* BEGIN CONTENTS OF README.TXT -------------------------------------
|
||||
The ConvexDecomposition library was written by John W. Ratcliff mailto:jratcliffscarab@gmail.com
|
||||
|
||||
What is Convex Decomposition?
|
||||
|
||||
Convex Decomposition is when you take an arbitrarily complex triangle mesh and sub-divide it into
|
||||
a collection of discrete compound pieces (each represented as a convex hull) to approximate
|
||||
the original shape of the objet.
|
||||
|
||||
This is required since few physics engines can treat aribtrary triangle mesh objects as dynamic
|
||||
objects. Even those engines which can handle this use case incurr a huge performance and memory
|
||||
penalty to do so.
|
||||
|
||||
By breaking a complex triangle mesh up into a discrete number of convex components you can greatly
|
||||
improve performance for dynamic simulations.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This code is released under the MIT license.
|
||||
|
||||
The code is functional but could use the following improvements:
|
||||
|
||||
(1) The convex hull generator, originally written by Stan Melax, could use some major code cleanup.
|
||||
|
||||
(2) The code to remove T-junctions appears to have a bug in it. This code was working fine before,
|
||||
but I haven't had time to debug why it stopped working.
|
||||
|
||||
(3) Island generation once the mesh has been split is currently disabled due to the fact that the
|
||||
Remove Tjunctions functionality has a bug in it.
|
||||
|
||||
(4) The code to perform a raycast against a triangle mesh does not currently use any acceleration
|
||||
data structures.
|
||||
|
||||
(5) When a split is performed, the surface that got split is not 'capped'. This causes a problem
|
||||
if you use a high recursion depth on your convex decomposition. It will cause the object to
|
||||
be modelled as if it had a hollow interior. A lot of work was done to solve this problem, but
|
||||
it hasn't been integrated into this code drop yet.
|
||||
|
||||
|
||||
*/// ---------- END CONTENTS OF README.TXT ----------------------------
|
||||
|
||||
|
||||
// a set of routines that let you do common 3d math
|
||||
// operations without any vector, matrix, or quaternion
|
||||
// classes or templates.
|
||||
//
|
||||
// a vector (or point) is a 'NxF32 *' to 3 floating point numbers.
|
||||
// a matrix is a 'NxF32 *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
|
||||
// a quaternion is a 'NxF32 *' to 4 floats representing a quaternion x,y,z,w
|
||||
//
|
||||
//
|
||||
/*!
|
||||
**
|
||||
** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com
|
||||
**
|
||||
** Portions of this source has been released with the PhysXViewer application, as well as
|
||||
** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
|
||||
**
|
||||
** If you find this code useful or you are feeling particularily generous I would
|
||||
** ask that you please go to http://www.amillionpixels.us and make a donation
|
||||
** to Troy DeMolay.
|
||||
**
|
||||
** DeMolay is a youth group for young men between the ages of 12 and 21.
|
||||
** It teaches strong moral principles, as well as leadership skills and
|
||||
** public speaking. The donations page uses the 'pay for pixels' paradigm
|
||||
** where, in this case, a pixel is only a single penny. Donations can be
|
||||
** made for as small as $4 or as high as a $100 block. Each person who donates
|
||||
** will get a link to their own site as well as acknowledgement on the
|
||||
** donations blog located here http://www.amillionpixels.blogspot.com/
|
||||
**
|
||||
** If you wish to contact me you can use the following methods:
|
||||
**
|
||||
** Skype ID: jratcliff63367
|
||||
** Yahoo: jratcliff63367
|
||||
** AOL: jratcliff1961
|
||||
** email: jratcliffscarab@gmail.com
|
||||
**
|
||||
**
|
||||
** The MIT license:
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and associated documentation files (the "Software"), to deal
|
||||
** in the Software without restriction, including without limitation the rights
|
||||
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
** copies of the Software, and to permit persons to whom the Software is furnished
|
||||
** to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in all
|
||||
** copies or substantial portions of the Software.
|
||||
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class TVec
|
||||
{
|
||||
public:
|
||||
TVec(NxF64 _x, NxF64 _y, NxF64 _z) { x = _x; y = _y; z = _z; };
|
||||
TVec(void) { };
|
||||
|
||||
NxF64 x;
|
||||
NxF64 y;
|
||||
NxF64 z;
|
||||
};
|
||||
|
||||
|
||||
class CTriangulator
|
||||
{
|
||||
public:
|
||||
/// Default constructor
|
||||
CTriangulator();
|
||||
|
||||
/// Default destructor
|
||||
virtual ~CTriangulator();
|
||||
|
||||
/// Returns the given point in the triangulator array
|
||||
inline TVec get(const TU32 id) { return mPoints[id]; }
|
||||
|
||||
virtual void reset(void)
|
||||
{
|
||||
mInputPoints.clear();
|
||||
mPoints.clear();
|
||||
mIndices.clear();
|
||||
}
|
||||
|
||||
virtual void addPoint(NxF64 x, NxF64 y, NxF64 z)
|
||||
{
|
||||
TVec v(x, y, z);
|
||||
// update bounding box...
|
||||
if (mInputPoints.empty())
|
||||
{
|
||||
mMin = v;
|
||||
mMax = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x < mMin.x)
|
||||
{
|
||||
mMin.x = x;
|
||||
}
|
||||
if (y < mMin.y)
|
||||
{
|
||||
mMin.y = y;
|
||||
}
|
||||
if (z < mMin.z)
|
||||
{
|
||||
mMin.z = z;
|
||||
}
|
||||
|
||||
if (x > mMax.x)
|
||||
{
|
||||
mMax.x = x;
|
||||
}
|
||||
if (y > mMax.y)
|
||||
{
|
||||
mMax.y = y;
|
||||
}
|
||||
if (z > mMax.z)
|
||||
{
|
||||
mMax.z = z;
|
||||
}
|
||||
}
|
||||
mInputPoints.push_back(v);
|
||||
}
|
||||
|
||||
// Triangulation happens in 2d. We could inverse transform the polygon around the normal direction, or we just use the two most signficant axes
|
||||
// Here we find the two longest axes and use them to triangulate. Inverse transforming them would introduce more doubleing point error and isn't worth it.
|
||||
virtual NxU32* triangulate(NxU32& tcount, NxF64 epsilon)
|
||||
{
|
||||
NxU32* ret = 0;
|
||||
tcount = 0;
|
||||
mEpsilon = epsilon;
|
||||
|
||||
if (!mInputPoints.empty())
|
||||
{
|
||||
mPoints.clear();
|
||||
|
||||
NxF64 dx = mMax.x - mMin.x; // locate the first, second and third longest edges and store them in i1, i2, i3
|
||||
NxF64 dy = mMax.y - mMin.y;
|
||||
NxF64 dz = mMax.z - mMin.z;
|
||||
|
||||
NxU32 i1, i2, i3;
|
||||
|
||||
if (dx > dy && dx > dz)
|
||||
{
|
||||
i1 = 0;
|
||||
if (dy > dz)
|
||||
{
|
||||
i2 = 1;
|
||||
i3 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i2 = 2;
|
||||
i3 = 1;
|
||||
}
|
||||
}
|
||||
else if (dy > dx && dy > dz)
|
||||
{
|
||||
i1 = 1;
|
||||
if (dx > dz)
|
||||
{
|
||||
i2 = 0;
|
||||
i3 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
i2 = 2;
|
||||
i3 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i1 = 2;
|
||||
if (dx > dy)
|
||||
{
|
||||
i2 = 0;
|
||||
i3 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i2 = 1;
|
||||
i3 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NxU32 pcount = (NxU32)mInputPoints.size();
|
||||
const NxF64* points = &mInputPoints[0].x;
|
||||
for (NxU32 i = 0; i < pcount; i++)
|
||||
{
|
||||
TVec v(points[i1], points[i2], points[i3]);
|
||||
mPoints.push_back(v);
|
||||
points += 3;
|
||||
}
|
||||
|
||||
mIndices.clear();
|
||||
triangulate(mIndices);
|
||||
tcount = (NxU32)mIndices.size() / 3;
|
||||
if (tcount)
|
||||
{
|
||||
ret = &mIndices[0];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual const NxF64* getPoint(NxU32 index)
|
||||
{
|
||||
return &mInputPoints[index].x;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
NxF64 mEpsilon;
|
||||
TVec mMin;
|
||||
TVec mMax;
|
||||
TVecVector mInputPoints;
|
||||
TVecVector mPoints;
|
||||
TU32Vector mIndices;
|
||||
|
||||
/// Tests if a point is inside the given triangle
|
||||
bool _insideTriangle(const TVec& A, const TVec& B, const TVec& C, const TVec& P);
|
||||
|
||||
/// Returns the area of the contour
|
||||
NxF64 _area();
|
||||
|
||||
bool _snip(NxI32 u, NxI32 v, NxI32 w, NxI32 n, NxI32* V);
|
||||
|
||||
/// Processes the triangulation
|
||||
void _process(TU32Vector& indices);
|
||||
/// Triangulates the contour
|
||||
void triangulate(TU32Vector& indices);
|
||||
};
|
||||
|
||||
/// Default constructor
|
||||
CTriangulator::CTriangulator(void)
|
||||
{
|
||||
}
|
||||
|
||||
/// Default destructor
|
||||
CTriangulator::~CTriangulator()
|
||||
{
|
||||
}
|
||||
|
||||
/// Triangulates the contour
|
||||
void CTriangulator::triangulate(TU32Vector& indices)
|
||||
{
|
||||
_process(indices);
|
||||
}
|
||||
|
||||
/// Processes the triangulation
|
||||
void CTriangulator::_process(TU32Vector& indices)
|
||||
{
|
||||
const NxI32 n = (const NxI32)mPoints.size();
|
||||
if (n < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
NxI32* V = (NxI32*)MEMALLOC_MALLOC(sizeof(NxI32) * n);
|
||||
|
||||
bool flipped = false;
|
||||
|
||||
if (0.0f < _area())
|
||||
{
|
||||
for (NxI32 v = 0; v < n; v++)
|
||||
{
|
||||
V[v] = v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flipped = true;
|
||||
for (NxI32 v = 0; v < n; v++)
|
||||
{
|
||||
V[v] = (n - 1) - v;
|
||||
}
|
||||
}
|
||||
|
||||
NxI32 nv = n;
|
||||
NxI32 count = 2 * nv;
|
||||
for (NxI32 m = 0, v = nv - 1; nv > 2; )
|
||||
{
|
||||
if (0 >= (count--))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NxI32 u = v;
|
||||
if (nv <= u)
|
||||
{
|
||||
u = 0;
|
||||
}
|
||||
v = u + 1;
|
||||
if (nv <= v)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
NxI32 w = v + 1;
|
||||
if (nv <= w)
|
||||
{
|
||||
w = 0;
|
||||
}
|
||||
|
||||
if (_snip(u, v, w, nv, V))
|
||||
{
|
||||
NxI32 a, b, c, s, t;
|
||||
a = V[u];
|
||||
b = V[v];
|
||||
c = V[w];
|
||||
if (flipped)
|
||||
{
|
||||
indices.push_back(a);
|
||||
indices.push_back(b);
|
||||
indices.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
indices.push_back(c);
|
||||
indices.push_back(b);
|
||||
indices.push_back(a);
|
||||
}
|
||||
m++;
|
||||
for (s = v, t = v + 1; t < nv; s++, t++)
|
||||
{
|
||||
V[s] = V[t];
|
||||
}
|
||||
nv--;
|
||||
count = 2 * nv;
|
||||
}
|
||||
}
|
||||
|
||||
MEMALLOC_FREE(V);
|
||||
}
|
||||
|
||||
/// Returns the area of the contour
|
||||
NxF64 CTriangulator::_area()
|
||||
{
|
||||
NxI32 n = (NxU32)mPoints.size();
|
||||
NxF64 A = 0.0f;
|
||||
for (NxI32 p = n - 1, q = 0; q < n; p = q++)
|
||||
{
|
||||
const TVec& pval = mPoints[p];
|
||||
const TVec& qval = mPoints[q];
|
||||
A += pval.x * qval.y - qval.x * pval.y;
|
||||
}
|
||||
A *= 0.5f;
|
||||
return A;
|
||||
}
|
||||
|
||||
bool CTriangulator::_snip(NxI32 u, NxI32 v, NxI32 w, NxI32 n, NxI32* V)
|
||||
{
|
||||
NxI32 p;
|
||||
|
||||
const TVec& A = mPoints[V[u]];
|
||||
const TVec& B = mPoints[V[v]];
|
||||
const TVec& C = mPoints[V[w]];
|
||||
|
||||
if (mEpsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (p = 0; p < n; p++)
|
||||
{
|
||||
if ((p == u) || (p == v) || (p == w))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const TVec& P = mPoints[V[p]];
|
||||
if (_insideTriangle(A, B, C, P))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Tests if a point is inside the given triangle
|
||||
bool CTriangulator::_insideTriangle(const TVec& A, const TVec& B, const TVec& C, const TVec& P)
|
||||
{
|
||||
NxF64 ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||||
NxF64 cCROSSap, bCROSScp, aCROSSbp;
|
||||
|
||||
ax = C.x - B.x;
|
||||
ay = C.y - B.y;
|
||||
bx = A.x - C.x;
|
||||
by = A.y - C.y;
|
||||
cx = B.x - A.x;
|
||||
cy = B.y - A.y;
|
||||
apx = P.x - A.x;
|
||||
apy = P.y - A.y;
|
||||
bpx = P.x - B.x;
|
||||
bpy = P.y - B.y;
|
||||
cpx = P.x - C.x;
|
||||
cpy = P.y - C.y;
|
||||
|
||||
aCROSSbp = ax * bpy - ay * bpx;
|
||||
cCROSSap = cx * apy - cy * apx;
|
||||
bCROSScp = bx * cpy - by * cpx;
|
||||
|
||||
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||||
}
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "DynamicArray2D.h"
|
||||
|
||||
// Editor
|
||||
#include "Util/fastlib.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction / destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CDynamicArray2D::CDynamicArray2D(unsigned int iDimension1, unsigned int iDimension2)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Declare a 2D array on the free store
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Save the position of the array dimensions
|
||||
m_Dimension1 = iDimension1;
|
||||
m_Dimension2 = iDimension2;
|
||||
|
||||
// First dimension
|
||||
m_Array = new float* [m_Dimension1];
|
||||
assert(m_Array);
|
||||
|
||||
// Second dimension
|
||||
for (i = 0; i < m_Dimension1; ++i)
|
||||
{
|
||||
m_Array[i] = new float[m_Dimension2];
|
||||
|
||||
// Init all fields with 0
|
||||
memset(&m_Array[i][0], 0, m_Dimension2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
CDynamicArray2D::~CDynamicArray2D()
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Remove the 2D array and all its sub arrays from the free store
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < m_Dimension1; ++i)
|
||||
{
|
||||
delete [] m_Array[i];
|
||||
}
|
||||
|
||||
delete [] m_Array;
|
||||
m_Array = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void CDynamicArray2D::ScaleImage(CDynamicArray2D* pDestination)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Scale an image stored (in an array class) to a new size
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned int i, j, iOldWidth;
|
||||
int iXSrcFl, iXSrcCe, iYSrcFl, iYSrcCe;
|
||||
float fXSrc, fYSrc;
|
||||
float fHeight[4];
|
||||
float fHeightWeight[4];
|
||||
float fHeightBottom;
|
||||
float fHeightTop;
|
||||
|
||||
assert(pDestination);
|
||||
assert(pDestination->m_Dimension1 > 1);
|
||||
|
||||
// Width has to be zero based, not a count
|
||||
iOldWidth = m_Dimension1 - 1;
|
||||
|
||||
// Loop trough each field of the new image and interpolate the value
|
||||
// from the source heightmap
|
||||
for (i = 0; i < pDestination->m_Dimension1; i++)
|
||||
{
|
||||
// Calculate the average source array position
|
||||
fXSrc = i / (float) pDestination->m_Dimension1 * iOldWidth;
|
||||
assert(fXSrc >= 0.0f && fXSrc <= iOldWidth);
|
||||
|
||||
// Precalculate floor and ceiling values. Use fast asm integer floor and
|
||||
// fast asm float / integer conversion
|
||||
iXSrcFl = ifloor(fXSrc);
|
||||
iXSrcCe = FloatToIntRet((float) ceil(fXSrc));
|
||||
|
||||
// Distribution between left and right height values
|
||||
fHeightWeight[0] = (float) iXSrcCe - fXSrc;
|
||||
fHeightWeight[1] = fXSrc - (float) iXSrcFl;
|
||||
|
||||
// Avoid error when floor() and ceil() return the same value
|
||||
if (fHeightWeight[0] == 0.0f && fHeightWeight[1] == 0.0f)
|
||||
{
|
||||
fHeightWeight[0] = 0.5f;
|
||||
fHeightWeight[1] = 0.5f;
|
||||
}
|
||||
|
||||
for (j = 0; j < pDestination->m_Dimension1; j++)
|
||||
{
|
||||
// Calculate the average source array position
|
||||
fYSrc = j / (float) pDestination->m_Dimension1 * iOldWidth;
|
||||
assert(fYSrc >= 0.0f && fYSrc <= iOldWidth);
|
||||
|
||||
// Precalculate floor and ceiling values. Use fast asm integer floor and
|
||||
// fast asm float / integer conversion
|
||||
iYSrcFl = ifloor(fYSrc);
|
||||
iYSrcCe = FloatToIntRet((float) ceil(fYSrc));
|
||||
|
||||
// Get the four nearest height values
|
||||
fHeight[0] = m_Array[iXSrcFl][iYSrcFl];
|
||||
fHeight[1] = m_Array[iXSrcCe][iYSrcFl];
|
||||
fHeight[2] = m_Array[iXSrcFl][iYSrcCe];
|
||||
fHeight[3] = m_Array[iXSrcCe][iYSrcCe];
|
||||
|
||||
// Calculate how much weight each height value has
|
||||
|
||||
// Distribution between top and bottom height values
|
||||
fHeightWeight[2] = (float) iYSrcCe - fYSrc;
|
||||
fHeightWeight[3] = fYSrc - (float) iYSrcFl;
|
||||
|
||||
// Avoid error when floor() and ceil() return the same value
|
||||
if (fHeightWeight[2] == 0.0f && fHeightWeight[3] == 0.0f)
|
||||
{
|
||||
fHeightWeight[2] = 0.5f;
|
||||
fHeightWeight[3] = 0.5f;
|
||||
}
|
||||
|
||||
// Interpolate between the four nearest height values
|
||||
|
||||
// Get the height for the given X position trough interpolation between
|
||||
// the left and the right height
|
||||
fHeightBottom = (fHeight[0] * fHeightWeight[0] + fHeight[1] * fHeightWeight[1]);
|
||||
fHeightTop = (fHeight[2] * fHeightWeight[0] + fHeight[3] * fHeightWeight[1]);
|
||||
|
||||
// Set the new value in the destination heightmap
|
||||
pDestination->m_Array[i][j] = fHeightBottom * fHeightWeight[2] + fHeightTop * fHeightWeight[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Interface of the class CDynamicArray.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_DYNAMICARRAY2D_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_DYNAMICARRAY2D_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class CDynamicArray2D
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
CDynamicArray2D(unsigned int iDimension1, unsigned int iDimension2);
|
||||
// destructor
|
||||
virtual ~CDynamicArray2D();
|
||||
//
|
||||
void ScaleImage(CDynamicArray2D* pDestination);
|
||||
|
||||
|
||||
float** m_Array; //
|
||||
|
||||
private:
|
||||
|
||||
unsigned int m_Dimension1; //
|
||||
unsigned int m_Dimension2; //
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_DYNAMICARRAY2D_H
|
||||
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "GdiUtil.h"
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
|
||||
QColor ScaleColor(const QColor& c, float aScale)
|
||||
{
|
||||
QColor aColor = c;
|
||||
if (!aColor.isValid())
|
||||
{
|
||||
// help out scaling, by starting at very low black
|
||||
aColor = QColor(1, 1, 1);
|
||||
}
|
||||
|
||||
const float r = static_cast<float>(aColor.red()) * aScale;
|
||||
const float g = static_cast<float>(aColor.green()) * aScale;
|
||||
const float b = static_cast<float>(aColor.blue()) * aScale;
|
||||
|
||||
return QColor(AZStd::clamp(static_cast<int>(r), 0, 255), AZStd::clamp(static_cast<int>(g), 0, 255), AZStd::clamp(static_cast<int>(b), 0, 255));
|
||||
}
|
||||
|
||||
CAlphaBitmap::CAlphaBitmap()
|
||||
{
|
||||
m_width = m_height = 0;
|
||||
}
|
||||
|
||||
CAlphaBitmap::~CAlphaBitmap()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
bool CAlphaBitmap::Create(void* pData, UINT aWidth, UINT aHeight, bool bVerticalFlip, bool bPremultiplyAlpha)
|
||||
{
|
||||
if (!aWidth || !aHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bmp = QImage(aWidth, aHeight, QImage::Format_RGBA8888);
|
||||
if (m_bmp.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<UINT> vBuffer;
|
||||
|
||||
if (pData)
|
||||
{
|
||||
// copy over the raw 32bpp data
|
||||
bVerticalFlip = !bVerticalFlip; // in Qt, the flip is not required. Still, keep the API behaving the same
|
||||
if (bVerticalFlip)
|
||||
{
|
||||
UINT nBufLen = aWidth * aHeight;
|
||||
vBuffer.resize(nBufLen);
|
||||
|
||||
if (IsBadReadPtr(pData, nBufLen * 4))
|
||||
{
|
||||
//TODO: remove after testing alot the browser, it doesnt happen anymore
|
||||
QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("Bad image data ptr!"));
|
||||
Free();
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!vBuffer.empty());
|
||||
|
||||
if (vBuffer.empty())
|
||||
{
|
||||
Free();
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT scanlineSize = aWidth * 4;
|
||||
|
||||
for (UINT i = 0, iCount = aHeight; i < iCount; ++i)
|
||||
{
|
||||
// top scanline position
|
||||
UINT* pTopScanPos = (UINT*)&vBuffer[0] + i * aWidth;
|
||||
// bottom scanline position
|
||||
UINT* pBottomScanPos = (UINT*)pData + (aHeight - i - 1) * aWidth;
|
||||
|
||||
// save a scanline from top
|
||||
memcpy(pTopScanPos, pBottomScanPos, scanlineSize);
|
||||
}
|
||||
|
||||
pData = &vBuffer[0];
|
||||
}
|
||||
|
||||
// premultiply alpha, AlphaBlend GDI expects it
|
||||
if (bPremultiplyAlpha)
|
||||
{
|
||||
for (UINT y = 0; y < aHeight; ++y)
|
||||
{
|
||||
BYTE* pPixel = (BYTE*) pData + aWidth * 4 * y;
|
||||
|
||||
for (UINT x = 0; x < aWidth; ++x)
|
||||
{
|
||||
pPixel[0] = ((int)pPixel[0] * pPixel[3] + 127) >> 8;
|
||||
pPixel[1] = ((int)pPixel[1] * pPixel[3] + 127) >> 8;
|
||||
pPixel[2] = ((int)pPixel[2] * pPixel[3] + 127) >> 8;
|
||||
pPixel += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(m_bmp.bits(), pData, aWidth * aHeight * 4);
|
||||
|
||||
if (m_bmp.isNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bmp.fill(Qt::transparent);
|
||||
}
|
||||
|
||||
// we dont need this screen DC anymore
|
||||
m_width = aWidth;
|
||||
m_height = aHeight;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage& CAlphaBitmap::GetBitmap()
|
||||
{
|
||||
return m_bmp;
|
||||
}
|
||||
|
||||
void CAlphaBitmap::Free()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
UINT CAlphaBitmap::GetWidth()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
UINT CAlphaBitmap::GetHeight()
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void CheckerboardFillRect(QPainter* pGraphics, const QRect& rRect, int checkDiameter, const QColor& aColor1, const QColor& aColor2)
|
||||
{
|
||||
pGraphics->save();
|
||||
pGraphics->setClipRect(rRect);
|
||||
// Create a checkerboard background for easier readability
|
||||
pGraphics->fillRect(rRect, aColor1);
|
||||
QBrush lightBrush(aColor2);
|
||||
|
||||
// QRect bottom/right methods are short one unit for legacy reasons. Compute bottomr/right of the rectange ourselves to get the full size.
|
||||
const int rectRight = rRect.x() + rRect.width();
|
||||
const int rectBottom = rRect.y() + rRect.height();
|
||||
|
||||
for (int i = rRect.left(); i < rectRight; i += checkDiameter)
|
||||
{
|
||||
for (int j = rRect.top(); j < rectBottom; j += checkDiameter)
|
||||
{
|
||||
if ((i / checkDiameter) % 2 ^ (j / checkDiameter) % 2)
|
||||
{
|
||||
pGraphics->fillRect(QRect(i, j, checkDiameter, checkDiameter), lightBrush);
|
||||
}
|
||||
}
|
||||
}
|
||||
pGraphics->restore();
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Utilitarian classes for double buffer GDI rendering and 32bit bitmaps
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTIL_GDIUTIL_H
|
||||
#define CRYINCLUDE_EDITOR_UTIL_GDIUTIL_H
|
||||
#pragma once
|
||||
|
||||
QColor ScaleColor(const QColor& coor, float aScale);
|
||||
|
||||
//! This class loads alpha-channel bitmaps and holds a DC for use with AlphaBlend function
|
||||
class CRYEDIT_API CAlphaBitmap
|
||||
{
|
||||
public:
|
||||
|
||||
CAlphaBitmap();
|
||||
~CAlphaBitmap();
|
||||
|
||||
//! creates the bitmap from raw 32bpp data
|
||||
//! \param pData the 32bpp raw image data, RGBA, can be nullptr and it would create just an empty bitmap
|
||||
//! \param aWidth the bitmap width
|
||||
//! \param aHeight the bitmap height
|
||||
bool Create(void* pData, UINT aWidth, UINT aHeight, bool bVerticalFlip = false, bool bPremultiplyAlpha = false);
|
||||
//! \return the actual bitmap
|
||||
QImage& GetBitmap();
|
||||
//! free the bitmap and DC
|
||||
void Free();
|
||||
//! \return bitmap width
|
||||
UINT GetWidth();
|
||||
//! \return bitmap height
|
||||
UINT GetHeight();
|
||||
|
||||
protected:
|
||||
|
||||
QImage m_bmp;
|
||||
UINT m_width, m_height;
|
||||
};
|
||||
|
||||
//! Fill a rectangle with a checkerboard pattern.
|
||||
//! \param pGraphics The Graphics object used for drawing
|
||||
//! \param rRect The rectangle to be filled
|
||||
//! \param checkDiameter the diameter of the check squares
|
||||
//! \param aColor1 the color that starts in the top left corner check square
|
||||
//! \param aColor2 the second color used for check squares
|
||||
void CheckerboardFillRect(QPainter* pGraphics, const QRect& rRect, int checkDiameter, const QColor& aColor1, const QColor& aColor2);
|
||||
#endif // CRYINCLUDE_EDITOR_UTIL_GDIUTIL_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue