Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,87 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorCommon_precompiled.h"
#include <ActionOutput.h>
#include <QWidget>
namespace AZ
{
ActionOutput::ActionOutput()
: m_errorCount(0)
, m_warningCount(0)
{
}
void ActionOutput::AddError(const AZStd::string& error)
{
AddError(error, "");
}
void ActionOutput::AddError(const AZStd::string& error, const AZStd::string& details)
{
m_errorToDetails[error].push_back(details);
++m_errorCount;
}
bool ActionOutput::HasAnyErrors() const
{
return m_errorCount > 0;
}
AZStd::string ActionOutput::BuildErrorMessage() const
{
return BuildMessage(m_errorToDetails);
}
void ActionOutput::AddWarning(const AZStd::string& warning)
{
AddWarning(warning, "");
}
void ActionOutput::AddWarning(const AZStd::string& warning, const AZStd::string& details)
{
m_warningToDetails[warning].push_back(details);
++m_warningCount;
}
bool ActionOutput::HasAnyWarnings() const
{
return m_warningCount > 0;
}
AZStd::string ActionOutput::BuildWarningMessage() const
{
return BuildMessage(m_warningToDetails);
}
AZStd::string ActionOutput::BuildMessage(const IssueToDetails& issues) const
{
AZStd::string message;
for (const auto& it : issues)
{
message += it.first;
message += ":\n";
const DetailList& details = it.second;
for (size_t i = 0; i < details.size(); ++i)
{
message += " ";
message += details[i];
message += "\n";
}
message += "\n";
}
return message;
}
}
@@ -0,0 +1,60 @@
#pragma once
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <EditorCommonAPI.h>
namespace AZ
{
// Stores the error output from save actions. Pairs error messages with a "details" context. That way if you could
// do something like:
// output->AddError("Failed to save file", fileName);
//
// Then if that error gets added a few times with different files, the final error message will be aggregated as
// follows:
// Failed to save file:
// thing1.cdf
// thing2.chr
class EDITOR_COMMON_API ActionOutput
{
public:
using DetailList = AZStd::vector<AZStd::string>;
using IssueToDetails = AZStd::map<AZStd::string, DetailList>;
ActionOutput();
void AddError(const AZStd::string& error);
void AddError(const AZStd::string& error, const AZStd::string& details);
bool HasAnyErrors() const;
AZStd::string BuildErrorMessage() const;
void AddWarning(const AZStd::string& error);
void AddWarning(const AZStd::string& error, const AZStd::string& details);
bool HasAnyWarnings() const;
AZStd::string BuildWarningMessage() const;
private:
AZStd::string BuildMessage(const IssueToDetails& issues) const;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
IssueToDetails m_errorToDetails;
IssueToDetails m_warningToDetails;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
int m_errorCount;
int m_warningCount;
};
}
@@ -0,0 +1,15 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "../../Editor/RenderHelpers/AxisHelperShared.inl"
@@ -0,0 +1,360 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "BatchFileDialog.h"
#include "QPropertyTree/QPropertyDialog.h"
#include "Serialization/StringList.h"
#include "Serialization/STL.h"
#include "Serialization/IArchive.h"
#include "Serialization/STLImpl.h"
#include "IEditor.h"
#include "Pak/CryPakUtils.h"
#include <vector>
#include <AzFramework/Archive/IArchive.h>
#include <StringUtils.h>
#include <QApplication>
#include <QMessageBox>
#include <QBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QFileDialog>
#include <Util/PathUtil.h>
#include <QDirIterator>
struct SBatchFileItem
{
bool selected;
string path;
bool checkable = false;
bool operator<(const SBatchFileItem& rhs) const { return path < rhs.path; }
void Serialize(Serialization::IArchive& ar)
{
// -------------------------------------------------------------------
// Note: The property tree label modifiers used below indicate...
// ! - Readonly, you can't modify the path
// ^ - Raise location to the parent (the index indicator)
// < - Take up the rest of the space
// -------------------------------------------------------------------
if (!checkable)
{
ar(selected, "selected", "^");
}
auto gamePath = PathUtil::MakeGamePath(path);
ar(gamePath, "path", "!^<");
}
};
typedef std::vector<SBatchFileItem> SBatchFileItems;
struct CBatchFileDialog::SContent
{
SBatchFileItems items;
string listLabel;
SContent(const char* itemsLabelText, bool readonlyList)
{
// Respect the readonly settings
if (readonlyList)
{
listLabel += "!";
}
// Label Size (5px per character)
auto labelSize = static_cast<int>(strlen(itemsLabelText)) * 5;
{
// Format is: >#>+ where the >#> indicates the label size, and the + indicates end of all row formatting
char buffer[16];
sprintf_s(buffer, sizeof(buffer), ">%i>+", labelSize);
listLabel += buffer;
}
// Add the actual label text (the text that is seen)
listLabel += itemsLabelText;
}
void Serialize(Serialization::IArchive& ar)
{
ar(items, "items", listLabel.c_str());
}
};
static bool ReadFile(std::vector<char>* buffer, const char* path)
{
FILE* f = nullptr;
azfopen(&f, path, "rb");
if (!f)
{
return false;
}
fseek(f, 0, SEEK_END);
size_t len = (size_t)ftell(f);
fseek(f, 0, SEEK_SET);
buffer->resize(len);
bool result = true;
if (len)
{
result = fread(&(*buffer)[0], 1, len, f) == len;
}
fclose(f);
return result;
}
static void SplitLines(std::vector<string>* lines, const char* start, const char* end)
{
const char* p = start;
const char* lineStart = start;
while (true)
{
if (p == end || *p == '\r' || *p == '\n')
{
if (p != lineStart)
{
string line(lineStart, p);
bool hasPrintableChars = false;
for (size_t i = 0; i < line.size(); ++i)
{
if (!isspace(line[i]))
{
hasPrintableChars = true;
}
}
if (hasPrintableChars)
{
lines->push_back(line);
}
}
lineStart = p + 1;
if (p == end)
{
break;
}
}
++p;
}
}
static string NormalizePath(const char* path)
{
string result = path;
result.replace('\\', '/');
result.MakeLower();
// strip .phys extensions in case list of .cdf is provided
string::size_type dotPos = result.rfind('.');
if (dotPos != string::npos)
{
if (_stricmp(result.c_str() + dotPos, ".phys"))
{
result.erase(dotPos, 5);
}
}
return result;
}
static bool IsEquivalentPath(const char* pathA, const char* pathB)
{
string normalizedA = NormalizePath(pathA);
string normalizedB = NormalizePath(pathB);
return normalizedA == normalizedB;
}
void CBatchFileDialog::OnLoadList()
{
QString existingFile = QFileDialog::getOpenFileName(m_dialog, "Load file list...", QString(), QString("Text Files (*.txt)"));
if (existingFile.isEmpty())
{
return;
}
string path = existingFile.toLocal8Bit().data();
std::vector<char> content;
ReadFile(&content, path.c_str());
std::vector<string> lines;
SplitLines(&lines, &content[0], &content[0] + content.size());
for (size_t i = 0; i < m_content->items.size(); ++i)
{
m_content->items[i].selected = false;
}
for (size_t i = 0; i < lines.size(); ++i)
{
const char* line = lines[i].c_str();
for (size_t j = 0; j < m_content->items.size(); ++j)
{
const char* itemPath = m_content->items[j].path.c_str();
if (IsEquivalentPath(line, itemPath))
{
m_content->items[j].selected = true;
break;
}
}
}
m_dialog->revert();
}
void CBatchFileDialog::OnSelectAll()
{
for (size_t i = 0; i < m_content->items.size(); ++i)
{
m_content->items[i].selected = true;
}
m_dialog->revert();
}
void CBatchFileDialog::OnSelectNone()
{
for (size_t i = 0; i < m_content->items.size(); ++i)
{
m_content->items[i].selected = false;
}
m_dialog->revert();
}
bool EDITOR_COMMON_API ShowBatchFileDialog(Serialization::StringList* result, const SBatchFileSettings& settings, QWidget* parent)
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
CBatchFileDialog::SContent content(settings.listLabel, settings.readonlyList);
if (settings.scanExtension[0] != '\0')
{
if (settings.useCryPak)
{
AZStd::vector<AZStd::string> files;
string mask = "*.";
mask += settings.scanExtension;
SDirectoryEnumeratorHelper helper;
helper.ScanDirectoryRecursive(gEnv->pCryPak, Path::GetEditingGameDataFolder().c_str(), "", mask.c_str(), files);
for (int k = 0; k < files.size(); ++k)
{
SBatchFileItem item;
item.checkable = settings.filesAreCheckable;
item.selected = true;
item.path = { files[k].data(), files[k].size() };
content.items.push_back(item);
}
}
else
{
string gameFolder = Path::GetEditingGameDataFolder().c_str();
int modIndex = 0;
string gamePrefix = GetIEditor()->GetPrimaryCDFolder().toUtf8().data();
if (!gamePrefix.empty() && gamePrefix[gamePrefix.size() - 1] != '\\')
{
gamePrefix += "\\";
}
gamePrefix += gameFolder;
if (!gamePrefix.empty() && gamePrefix[gamePrefix.size() - 1] != '\\')
{
gamePrefix += "\\";
}
gamePrefix.replace('/', '\\');
QString mask = "*." + QString(settings.scanExtension);
QDirIterator dirIterator(QString(gamePrefix), QStringList() << mask, QDir::Files, QDirIterator::Subdirectories);
while (dirIterator.hasNext())
{
SBatchFileItem item;
item.selected = true;
QByteArray array = dirIterator.next().toUtf8();
item.path = string(array);
item.path.replace('/', '\\');
content.items.push_back(item);
}
}
}
content.items.reserve(content.items.size() + settings.explicitFileList.size());
for (size_t i = 0; i < settings.explicitFileList.size(); ++i)
{
SBatchFileItem item;
item.path = settings.explicitFileList[i].c_str();
item.selected = true;
content.items.push_back(item);
}
std::sort(content.items.begin(), content.items.end());
QApplication::restoreOverrideCursor();
QPropertyDialog dialog(parent);
dialog.setSerializer(Serialization::SStruct(content));
dialog.setWindowTitle(settings.title);
dialog.setWindowStateFilename(settings.stateFilename);
dialog.setSizeHint(QSize(settings.defaultWidth, settings.defaultHeight));
dialog.setMinimumSize(QSize(540, 250));
CBatchFileDialog handler;
handler.m_dialog = &dialog;
handler.m_content = &content;
QBoxLayout* topRow = new QBoxLayout(QBoxLayout::LeftToRight);
QLabel* label = new QLabel(settings.descriptionText);
QFont font;
font.setBold(true);
label->setFont(font);
topRow->addWidget(label, 1);
{
if (settings.allowListLoading && !settings.readonlyList)
{
QPushButton* loadListButton = new QPushButton("Load List...");
QObject::connect(loadListButton, SIGNAL(pressed()), &handler, SLOT(OnLoadList()));
topRow->addWidget(loadListButton);
}
QPushButton* selectAllButton = new QPushButton("Select All");
QObject::connect(selectAllButton, SIGNAL(pressed()), &handler, SLOT(OnSelectAll()));
topRow->addWidget(selectAllButton);
QPushButton* selectNoneButton = new QPushButton("Select None");
QObject::connect(selectNoneButton, SIGNAL(pressed()), &handler, SLOT(OnSelectNone()));
topRow->addWidget(selectNoneButton);
}
dialog.layout()->insertLayout(0, topRow);
if (parent)
{
QPoint center = parent->rect().center();
dialog.window()->move(max(0, center.x() - dialog.width() / 2),
max(0, center.y() - dialog.height() / 2));
}
int numFailed = 0;
int numSaved = 0;
std::vector<string> failedFiles;
if (dialog.exec() == QDialog::Accepted)
{
result->clear();
for (size_t i = 0; i < content.items.size(); ++i)
{
if (content.items[i].selected)
{
const char* path = content.items[i].path.c_str();
result->push_back(path);
}
}
return true;
}
return false;
}
#include <moc_BatchFileDialog.cpp>
@@ -0,0 +1,77 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
#define CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "EditorCommonAPI.h"
#include <QObject>
#include <Serialization/StringList.h>
#endif
// Private class, should not be used directly
class QWidget;
class QPropertyDialog;
class CBatchFileDialog
: public QObject
{
Q_OBJECT
public slots:
void OnSelectAll();
void OnSelectNone();
void OnLoadList();
public:
QPropertyDialog* m_dialog;
struct SContent;
SContent* m_content;
};
// ^^^
struct SBatchFileSettings
{
const char* scanExtension;
const char* scanFolder;
const char* title;
const char* descriptionText;
const char* listLabel;
const char* stateFilename;
bool useCryPak;
bool allowListLoading;
bool readonlyList;
bool filesAreCheckable;
Serialization::StringList explicitFileList;
int defaultWidth;
int defaultHeight;
SBatchFileSettings()
: useCryPak(true)
, readonlyList(true)
, filesAreCheckable(false)
, allowListLoading(true)
, descriptionText("Batch Selected Files")
, listLabel("Files")
, stateFilename("batchFileDialog.state")
, title("Batch Files")
, scanFolder("")
, scanExtension("*")
{
}
};
bool EDITOR_COMMON_API ShowBatchFileDialog(Serialization::StringList* filenames, const SBatchFileSettings& settings, QWidget* parent);
#endif // CRYINCLUDE_EDITORCOMMON_BATCHFILEDIALOG_H
@@ -0,0 +1,56 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
# Header only target to prevent linkage against editor libraries when it is not needed. Eventually the targets that depend
# on editor headers should cleanup dependencies and interact with the editor through buses or other mechanisms
ly_add_target(
NAME EditorCommon.Headers HEADERONLY
NAMESPACE Legacy
FILES_CMAKE
editorcommon_files.cmake
INCLUDE_DIRECTORIES
INTERFACE
.
)
ly_add_target(
NAME EditorCommon SHARED
NAMESPACE Legacy
AUTOMOC
AUTORCC
FILES_CMAKE
editorcommon_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
COMPILE_DEFINITIONS
PRIVATE
EDITOR_COMMON_EXPORTS
INTERFACE
EDITOR_COMMON_IMPORTS
BUILD_DEPENDENCIES
PRIVATE
3rdParty::zlib
3rdParty::Qt::Core
3rdParty::Qt::Widgets
Legacy::CryCommon
Legacy::EditorCore
AZ::AzCore
AZ::AzToolsFramework
AZ::AzQtComponents
)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,233 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include "CurveEditorContent.h"
#include <QWidget>
#include <Range.h>
class QMenu;
class CCurveEditorControl;
class CCurveEditorTangentControl;
struct ISplineInterpolator;
enum ETangent
{
ETangent_In,
ETangent_Out
};
enum ECurveEditorCurveType
{
eCECT_Bezier,
// 2D Bezier curves are used for better curve control, the editor
// will enforce that the resulting curve is always 1D.
eCECT_2DBezier,
};
namespace CurveEditorHelpers
{
// Picks a nice color value for a curve. Wraps around after 4.
EDITOR_COMMON_API ColorB GetCurveColor(const uint n);
EDITOR_COMMON_API QColor LerpColor(const QColor& a, const QColor& b, float k);
}
class EDITOR_COMMON_API CCurveEditor
: public QWidget
{
Q_OBJECT
public:
enum EOptOutFlags
{
EOptOutFree = 1 << 0,
EOptOutFlat = 1 << 1,
EOptOutLinear = 1 << 2,
EOptOutStep = 1 << 3,
EOptOutBezier = 1 << 4,
EOptOutSelectionKey = 1 << 5,
EOptOutSelectionInOutTangent = 1 << 6,
//steven@conffx added some optout options to allow easier graphical customization
EOptOutKeyIcon = 1 << 7,
EOptOutRuler = 1 << 8,
EOptOutTimeSlider = 1 << 9,
EOptOutBackground = 1 << 10,
EOptOutCustomPenColor = 1 << 11,
EOptOutControls = 1 << 12,
eOptOutDashedPath = 1 << 13,
EOptOutDefaultTooltip = 1 << 14,
EOptOutFitCurvesContextMenuOptions = 1 << 15,
EOptOutZoomingAndPanning = 1 << 16
};
CCurveEditor(QWidget* parent);
~CCurveEditor();
void SetContent(SCurveEditorContent* pContent);
SCurveEditorContent* Content() const { return m_pContent; }
void SetTime(const float time);
// The background in the time and value range will be drawn a bit brighter to indicate where keys
// should be placed. The curve editor does not enforce that the curves actually stay in those ranges.
void SetTimeRange(const float start, const float end);
void SetValueRange(const float min, const float max);
// Points cannot be added outside of the time range and the view will not move horizontally...zooming will only be done on the vertical axis
void EnforceTimeRange(const float start, const float end);
bool IsTimeRangeEnforced() const;
void ZoomToTimeRange(const float start, const float end);
void ZoomToValueRange(const float min, const float max);
void SetCurveType(ECurveEditorCurveType curveType);
void SetWeighted(bool bWeighted);
void SetHandlesVisible(bool bVisible);
void SetRulerVisible(bool bVisible);
void SetTimeSliderVisible(bool bVisible);
Vec2 TransformToScreenCoordinates(Vec2 graphPoint);
Vec2 TransformFromScreenCoordinates(Vec2 screenPoint);
// Removes parts of the popup-menu, use CCurveEditor::EMenuOptOutFlags
void SetOptOutFlags(int flags);
// Tools added to tool bar depend on options above
void PopulateControlContextMenu(QMenu* pToolBar);
virtual void paintEvent(QPaintEvent* pEvent) override;
void mousePressEvent(QMouseEvent* pEvent) override;
void mouseDoubleClickEvent(QMouseEvent* pEvent) override;
void mouseMoveEvent(QMouseEvent* pEvent) override;
void mouseReleaseEvent(QMouseEvent* pEvent) override;
void focusOutEvent(QFocusEvent* pEvent) override;
void wheelEvent(QWheelEvent* pEvent) override;
void keyPressEvent(QKeyEvent* pEvent) override;
QString static TangentTypeToString(SCurveEditorKey::ETangentType type);
void updateCurveKeyShapeColor(); // loop through curve keys and set shape color for them
void SetIconShapeColor(unsigned int key, QColor color);
void SetIconFillColor(unsigned int key, QColor color);
void SetIconImage(QString str);
void SetIconShapeMask(QColor color);
void SetIconFillMask(QColor color);
void SetIconToolTip(unsigned int key, QString str);
void SetIconSize(unsigned int key, unsigned int size);
void setPenColor(QColor color);
void ContentChanged();
void SortKeys(SCurveEditorCurve& curve);
std::pair<SCurveEditorCurve*, Vec2> HitDetectCurve(const QPoint point);
CCurveEditorControl* HitDetectKey(const QPoint point);
CCurveEditorTangentControl* HitDetectTangent(const QPoint point);
CCurveEditorControl* GetSelectedCurveKey();
QRectF GetBackgroundRect();
void SelectKey(CCurveEditorControl* pKeyToSelect, bool addToExistingSelection);
void SelectTangent(CCurveEditorTangentControl* pTangentToSelect);
void SelectInRect(const QRect& rect);
signals:
void SignalContentChanged();
void SignalScrub();
void SignalKeyMoved();
void SignalKeyMoveStarted();
void SignalKeySelected(CCurveEditorControl* selectedKey);
public slots:
void OnDeleteSelectedKeys();
void OnSetSelectedKeysTangentStandard();
void OnSetSelectedKeysTangentSmooth();
void OnSetSelectedKeysTangentFree();
void OnSetSelectedKeysTangentBezier();
void OnSetSelectedKeysTangentFlat();
void OnSetSelectedKeysTangentLinear();
void OnSetSelectedKeysInTangentFree();
void OnSetSelectedKeysInTangentFlat();
void OnSetSelectedKeysInTangentLinear();
void OnSetSelectedKeysInTangentStep();
void OnSetSelectedKeysInTangentBezier();
void OnSetSelectedKeysOutTangentFree();
void OnSetSelectedKeysOutTangentFlat();
void OnSetSelectedKeysOutTangentLinear();
void OnSetSelectedKeysOutTangentStep();
void OnSetSelectedKeysOutTangentBezier();
void OnFitCurvesHorizontally();
void OnFitCurvesVertically();
protected:
struct SMouseHandler
{
virtual ~SMouseHandler() = default;
virtual void mousePressEvent([[maybe_unused]] QMouseEvent* pEvent) {}
virtual void mouseDoubleClickEvent([[maybe_unused]] QMouseEvent* pEvent) {}
virtual void mouseMoveEvent([[maybe_unused]] QMouseEvent* pEvent) {}
virtual void mouseReleaseEvent([[maybe_unused]] QMouseEvent* pEvent) {}
virtual void focusOutEvent([[maybe_unused]] QFocusEvent* pEvent) {}
virtual void paintOver([[maybe_unused]] QPainter& painter) {}
};
struct SSelectionHandler;
struct SPanHandler;
struct SZoomHandler;
struct SMoveKeyHandler;
struct SRotateTangentHandler;
struct SScrubHandler;
QColor m_penColor;
void LeftButtonMousePressEvent(QMouseEvent* pEvent);
void MiddleButtonMousePressEvent(QMouseEvent* pEvent);
void RightButtonMousePressEvent(QMouseEvent* pEvent);
void DeleteMarkedKeys();
void SetTimeRange(const float start, const float end, bool enforce);
Vec2 ClosestPointOnCurve(const Vec2 point, const SCurveEditorCurve& curve, const ECurveEditorCurveType curveType);
bool AddPointToCurve(Vec2 point, SCurveEditorCurve* pCurve);
QRect GetCurveArea();
void SetSelectedKeysTangentType(const ETangent tangent, const SCurveEditorKey::ETangentType type);
void SmoothSelectedKeys();
void UpdateTangents();
SCurveEditorContent* m_pContent;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
std::unique_ptr<SMouseHandler> m_pMouseHandler;
ECurveEditorCurveType m_curveType;
bool m_bWeighted;
bool m_bHandlesVisible;
bool m_bRulerVisible;
bool m_bTimeSliderVisible;
float m_time;
Vec2 m_zoom;
Vec2 m_translation;
Range m_timeRange;
bool m_timeRangeEnforced;
Range m_valueRange;
int m_optOutFlags;
public:
QList<CCurveEditorControl*> m_pControlKeys;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
@@ -0,0 +1,155 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <Cry_Math.h>
#include <Cry_Color.h>
#include "Serialization/Strings.h"
#include "Serialization/SmartPtr.h"
#include "Serialization/Color.h"
#include "Serialization.h"
struct ISplineInterpolator;
struct SCurveEditorKey
{
SCurveEditorKey()
: m_bSelected(false)
, m_bModified(false)
, m_bAdded(false)
, m_bDeleted(false)
, m_time(0.0f)
, m_value(0.0f)
, m_inTangentType(eTangentType_Standard)
, m_outTangentType(eTangentType_Standard)
, m_inTangent(ZERO)
, m_outTangent(ZERO)
{
}
enum ETangentType
{
eTangentType_Standard, // Tangent freely rotates but will stay in sync with its pair if its pair is also standard
eTangentType_Free, // Tangent is completely free moving (does not sync with its pair)
eTangentType_Step, // Step immediately to value of next control point in tangent direction
eTangentType_Linear, // Tangent always points to next control point
eTangentType_Bezier, // Tangent is free moving and can be justified by user
eTangentType_Smooth, // Tangent is smoothed automatically based on direction/distance to neighboring controls
eTangentType_Flat, // Tangent is flattened (y = 0) - will still sync with its pair if both are flat
};
void Serialize(IArchive& ar)
{
ar(m_inTangentType, "inTangentType");
ar(m_outTangentType, "outTangentType");
ar(m_time, "time");
ar(m_value, "value");
ar(m_inTangent, "inTangent");
ar(m_outTangent, "outTangent");
}
bool m_bSelected : 1;
bool m_bModified : 1;
bool m_bAdded : 1;
bool m_bDeleted : 1;
ETangentType m_inTangentType : 4;
ETangentType m_outTangentType : 4;
float m_time;
float m_value;
// For 1D Bezier only the Y component is used
Vec2 m_inTangent;
Vec2 m_outTangent;
bool operator==(const SCurveEditorKey& rhs) const
{
return (m_inTangentType == rhs.m_inTangentType
&& m_outTangentType == rhs.m_outTangentType
&& m_time == rhs.m_time
&& m_value == rhs.m_value
&& m_inTangent == rhs.m_inTangent
&& m_outTangent == rhs.m_outTangent);
}
bool operator!=(const SCurveEditorKey& rhs) const
{
return !(*this == rhs);
}
};
struct SCurveEditorCurve
{
SCurveEditorCurve()
: m_bModified(false)
, m_defaultValue(0.0f)
, m_color(255, 255, 255)
, m_customInterpolator(nullptr)
{}
void Serialize(IArchive& ar)
{
ar(m_keys, "keys");
ar(m_defaultValue, "defaultValue");
ar(m_color, "color");
}
bool m_bModified : 1;
float m_defaultValue;
ColorB m_color;
// Setting m_customInterpolator will override spline-draw code.
// When used, its up to developer to fill and update all necessary keys.
ISplineInterpolator* m_customInterpolator;
std::vector<SCurveEditorKey> m_keys;
bool operator==(const SCurveEditorCurve& rhs) const
{
if (m_defaultValue != rhs.m_defaultValue
|| m_color != rhs.m_color
|| m_keys.size() != rhs.m_keys.size())
{
return false;
}
for (int i = 0; i < m_keys.size(); i++)
{
if (m_keys[i] != rhs.m_keys[i])
return false;
}
return true;
}
bool operator!=(const SCurveEditorCurve& rhs) const
{
return !(*this == rhs);
}
};
typedef std::vector<SCurveEditorCurve> TCurveEditorCurves;
struct SCurveEditorContent
{
void Serialize(IArchive& ar)
{
ar(m_curves, "curves");
}
TCurveEditorCurves m_curves;
};
@@ -0,0 +1,84 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Cry_Math.h>
#include <Cry_Color.h>
#include <Bezier.h>
#include <AnimTime.h>
#include "Serialization/Strings.h"
#include "Serialization/SmartPtr.h"
#include "Serialization/Color.h"
#include "Serialization.h"
struct SCurveEditorKey
{
SCurveEditorKey()
: m_time(0)
, m_bSelected(false)
, m_bModified(false)
, m_bAdded(false)
, m_bDeleted(false)
{
}
void Serialize(IArchive& ar)
{
ar(m_time);
ar(m_controlPoint);
}
SAnimTime m_time;
SBezierControlPoint m_controlPoint;
bool m_bSelected : 1;
bool m_bModified : 1;
bool m_bAdded : 1;
bool m_bDeleted : 1;
};
struct SCurveEditorCurve
{
SCurveEditorCurve()
: m_bModified(false)
, m_defaultValue(0.0f)
, m_color(255, 255, 255)
{}
void Serialize(IArchive& ar)
{
ar(m_keys, "keys");
ar(m_defaultValue, "defaultValue");
ar(m_color, "color");
}
bool m_bModified : 1;
float m_defaultValue;
ColorB m_color;
DynArray<char> userSideLoad;
std::vector<SCurveEditorKey> m_keys;
};
typedef std::vector<SCurveEditorCurve> TCurveEditorCurves;
struct SCurveEditorContent
{
void Serialize(IArchive& ar)
{
ar(m_curves, "curves");
}
TCurveEditorCurves m_curves;
};
@@ -0,0 +1,20 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CurveEditorContent.h"
SERIALIZATION_ENUM_BEGIN_NESTED(SCurveEditorKey, ETangentType, "TangentType")
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Custom, "Custom")
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Auto, "Smooth")
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Zero, "Zero")
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Step, "Step")
SERIALIZATION_ENUM_VALUE_NESTED(SCurveEditorKey, eTangentType_Linear, "Linear")
SERIALIZATION_ENUM_END()
@@ -0,0 +1,352 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorCommon_precompiled.h"
#include "CurveEditorControl.h"
#include <QPainter>
#include <QBitmap>
#include <QMouseEvent>
#include <algorithm>
#include "CurveEditor.h"
namespace
{
const int kDefaultControlVisualSize = 8;
const int kDefaultControlClickableSize = 10;
const int kDefaultTangentControlVisualSize = 6;
const int kDefaultTangentControlClickableSize = 8;
const int kDefaultTangentControlDistanceFromControl = 30;
void DrawPointRect(QPainter& painter, QPointF point, const QColor& color, int size)
{
painter.setBrush(QBrush(color));
painter.setPen(QColor(0, 0, 0));
float halfSize = size / 2.0f;
QPointF extents = QPointF(halfSize, halfSize);
painter.drawRect(QRectF(point - extents, point + extents));
}
}
CCurveEditorControl::CCurveEditorControl(CCurveEditor& curveEditor, SCurveEditorCurve& curve, SCurveEditorKey& key)
: m_CurveEditor(curveEditor)
, m_Curve(curve)
, m_Key(key)
, m_VisualSize(kDefaultControlVisualSize)
, m_ClickableSize(kDefaultControlClickableSize)
, m_pInTangent(new CCurveEditorTangentControl(*this, ETangent_In))
, m_pOutTangent(new CCurveEditorTangentControl(*this, ETangent_Out))
, m_filledPxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
, m_shapePxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
, m_icon(kDefaultControlVisualSize, kDefaultControlVisualSize)
, m_originalPxr(kDefaultControlVisualSize, kDefaultControlVisualSize)
, m_tip("")
, m_iconsize(16)
{
}
CCurveEditorControl::~CCurveEditorControl()
{
delete m_pInTangent;
delete m_pOutTangent;
}
CCurveEditor& CCurveEditorControl::GetCurveEditor() const
{
return m_CurveEditor;
}
SCurveEditorCurve& CCurveEditorControl::GetCurve() const
{
return m_Curve;
}
SCurveEditorKey& CCurveEditorControl::GetKey() const
{
return m_Key;
}
CCurveEditorTangentControl& CCurveEditorControl::GetInTangent()
{
return *m_pInTangent;
}
CCurveEditorTangentControl& CCurveEditorControl::GetOutTangent()
{
return *m_pOutTangent;
}
bool CCurveEditorControl::IsSelected() const
{
return m_Key.m_bSelected;
}
void CCurveEditorControl::SetSelected(bool selected)
{
m_Key.m_bSelected = selected;
m_pInTangent->SetVisible(selected);
m_pOutTangent->SetVisible(selected);
}
bool CCurveEditorControl::IsKeyMarkedForRemoval() const
{
return m_Key.m_bDeleted;
}
void CCurveEditorControl::MarkKeyForRemoval()
{
m_Key.m_bDeleted = true;
}
void CCurveEditorControl::Paint(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents)
{
const QColor pointColor = m_Key.m_bSelected ? palette.color(QPalette::Highlight) : QColor(255, 255, 255, 255);
if (paintInOutTangents)
{
m_pInTangent->Paint(painter, palette);
m_pOutTangent->Paint(painter, palette);
}
DrawPointRect(painter, GetScreenPosition(), pointColor, m_VisualSize);
}
void CCurveEditorControl::PaintIcon(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents)
{
if (paintInOutTangents)
{
m_pInTangent->Paint(painter, palette);
m_pOutTangent->Paint(painter, palette);
}
QPointF pos = GetScreenPosition();
float halfSize = m_iconsize / 2.0f;
QPointF extents = QPointF(halfSize, halfSize);
painter.drawPixmap(QRectF(GetScreenPosition() - extents, GetScreenPosition() + extents), m_icon, QRectF(0, 0, m_iconsize, m_iconsize));
}
bool CCurveEditorControl::IsMouseWithinControl(QPointF screenPos) const
{
QPointF keyPosition = GetScreenPosition();
QPointF deltaPos = screenPos - keyPosition;
float halfClickSize = m_ClickableSize / 2.0f;
return abs(deltaPos.x()) <= halfClickSize && abs(deltaPos.y()) <= halfClickSize;
}
QPointF CCurveEditorControl::GetScreenPosition() const
{
Vec2 screenPosition = m_CurveEditor.TransformToScreenCoordinates(Vec2(m_Key.m_time, m_Key.m_value));
return QPointF(screenPosition.x, screenPosition.y);
}
void CCurveEditorControl::BuildIcon()
{
m_filledPxr = QPixmap(m_originalPxr.size());
m_shapePxr = QPixmap(m_originalPxr.size());
m_shapePxr.fill(m_shapeColor);
m_filledPxr.fill(m_fillColor);
m_shapePxr.setMask(m_originalPxr.createMaskFromColor(m_shapeMask).createMaskFromColor(m_fillMask));
m_filledPxr.setMask(m_originalPxr.createMaskFromColor(m_fillMask, Qt::MaskOutColor));
QPainter painter(&m_shapePxr);
painter.drawPixmap(0, 0, m_filledPxr);
m_icon = m_shapePxr.scaled(m_iconsize, m_iconsize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
void CCurveEditorControl::SetIconFillMask(QColor color)
{
m_fillMask = color;
BuildIcon();
}
void CCurveEditorControl::SetIconShapeMask(QColor color)
{
m_shapeMask = color;
BuildIcon();
}
void CCurveEditorControl::SetIconImage(QString str)
{
m_originalPxr.load(str);
BuildIcon();
}
void CCurveEditorControl::SetIconFillColor(QColor color)
{
m_fillColor = color;
BuildIcon();
}
void CCurveEditorControl::SetIconShapeColor(QColor color)
{
m_shapeColor = color;
BuildIcon();
}
CCurveEditorTangentControl::CCurveEditorTangentControl(CCurveEditorControl& control, ETangent tangentDirection)
: m_Control(control)
, m_TangentDirection(tangentDirection)
, m_Visible(false)
, m_Selected(false)
, m_VisualSize(kDefaultTangentControlVisualSize)
, m_ClickableSize(kDefaultTangentControlClickableSize)
, m_DistanceFromControl(kDefaultTangentControlDistanceFromControl)
{
}
CCurveEditorTangentControl::~CCurveEditorTangentControl()
{
}
CCurveEditorControl& CCurveEditorTangentControl::GetControl()
{
return m_Control;
}
ETangent CCurveEditorTangentControl::GetTangentDirection() const
{
return m_TangentDirection;
}
bool CCurveEditorTangentControl::IsVisible() const
{
if (!m_Visible)
{
return false;
}
SCurveEditorKey::ETangentType tangentType;
if (m_TangentDirection == ETangent_In)
{
tangentType = m_Control.GetKey().m_inTangentType;
}
else
{
tangentType = m_Control.GetKey().m_outTangentType;
}
if (tangentType == SCurveEditorKey::eTangentType_Step)
{
return false;
}
// first in
if ((*m_Control.GetCurve().m_keys.begin()).m_time == m_Control.GetKey().m_time && m_TangentDirection == ETangent_In)
{
return false;
}
// last out
if ((*(m_Control.GetCurve().m_keys.end() - 1)).m_time == m_Control.GetKey().m_time && m_TangentDirection == ETangent_Out)
{
return false;
}
return true;
}
void CCurveEditorTangentControl::SetVisible(bool visible)
{
m_Visible = visible;
}
bool CCurveEditorTangentControl::IsSelected() const
{
return m_Selected;
}
void CCurveEditorTangentControl::SetSelected(bool selected)
{
m_Selected = selected;
}
void CCurveEditorTangentControl::SetVisualSize(int visualSize)
{
m_VisualSize = visualSize;
}
void CCurveEditorTangentControl::SetClickableSize(int clickableSize)
{
m_ClickableSize = clickableSize;
}
void CCurveEditorTangentControl::SetDistanceFromControl(int distanceFromControl)
{
m_DistanceFromControl = distanceFromControl;
}
void CCurveEditorTangentControl::Paint(QPainter& painter, const QPalette& palette)
{
if (!IsVisible())
{
return;
}
QPointF controlPosition = m_Control.GetScreenPosition();
QPointF tangentPosition = GetScreenPosition();
float highlightPercent;
if (m_Selected)
{
highlightPercent = 0.0f;
}
else
{
highlightPercent = 0.5f;
}
const QColor tangentColor = CurveEditorHelpers::LerpColor(palette.color(QPalette::Highlight), palette.color(QPalette::Window), highlightPercent);
const QPen tangentPen = QPen(tangentColor);
painter.setPen(tangentPen);
painter.drawLine(controlPosition, tangentPosition);
const QColor tangentControlColor = m_Selected ? palette.color(QPalette::Highlight) : palette.color(QPalette::Dark);
DrawPointRect(painter, tangentPosition, tangentControlColor, m_VisualSize);
}
bool CCurveEditorTangentControl::IsMouseWithinControl(QPointF screenPos) const
{
if (!IsVisible())
{
return false;
}
QPointF keyPosition = GetScreenPosition();
QPointF deltaPos = screenPos - keyPosition;
float halfClickSize = m_ClickableSize / 2.0f;
return abs(deltaPos.x()) <= halfClickSize && abs(deltaPos.y()) <= halfClickSize;
}
QPointF CCurveEditorTangentControl::GetScreenPosition() const
{
QPointF controlPosition = m_Control.GetScreenPosition();
Vec2 tangent;
if (m_TangentDirection == ETangent_In)
{
tangent = m_Control.GetKey().m_inTangent;
}
else
{
tangent = m_Control.GetKey().m_outTangent;
}
Vec2 tangentScreenPosition = m_Control.GetCurveEditor().TransformToScreenCoordinates(Vec2(m_Control.GetKey().m_time + tangent.x, m_Control.GetKey().m_value + tangent.y));
Vec2 transformedTangentDelta = (tangentScreenPosition - Vec2(aznumeric_cast<float>(controlPosition.x()), aznumeric_cast<float>(controlPosition.y()))).Normalize() * aznumeric_cast<float>(m_DistanceFromControl);
return controlPosition + QPointF(transformedTangentDelta.x, transformedTangentDelta.y);
}
@@ -0,0 +1,150 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "CurveEditor.h"
#include <QWidget>
class CCurveEditor;
class CCurveEditorTangentControl;
class QMouseEvent;
class QPainter;
class EDITOR_COMMON_API CCurveEditorControl
{
public:
CCurveEditorControl(CCurveEditor& curveEditor, SCurveEditorCurve& curve, SCurveEditorKey& key);
~CCurveEditorControl();
CCurveEditor& GetCurveEditor() const;
SCurveEditorCurve& GetCurve() const;
SCurveEditorKey& GetKey() const;
CCurveEditorTangentControl& GetInTangent();
CCurveEditorTangentControl& GetOutTangent();
void SetVisualSize(int visualSize)
{
m_VisualSize = visualSize;
}
void SetClickableSize(int clickableSize)
{
m_ClickableSize = clickableSize;
}
bool IsSelected() const;
void SetSelected(bool selected);
bool IsKeyMarkedForRemoval() const;
void MarkKeyForRemoval();
void Paint(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents);
void PaintIcon(QPainter& painter, const QPalette& palette, const bool& paintInOutTangents);
bool IsMouseWithinControl(QPointF screenPos) const;
QPointF GetScreenPosition() const;
QRect GetRect() const
{
return QRect(aznumeric_cast<int>(GetScreenPosition().x() - (m_VisualSize / 2)), aznumeric_cast<int>(GetScreenPosition().y() - (m_VisualSize / 2)), m_VisualSize, m_VisualSize);
}
void SetIconShapeColor(QColor color);
void SetIconFillColor(QColor color);
void SetIconImage(QString str);
void SetIconShapeMask(QColor color);
void SetIconFillMask(QColor color);
void SetIconToolTip(QString str)
{
m_tip = str;
}
void SetIconSize(int size)
{
m_iconsize = size;
BuildIcon();
}
QString GetToolTip() const { return m_tip; }
protected:
void BuildIcon();
private:
QPixmap m_icon;
QPixmap m_filledPxr;
QPixmap m_shapePxr;
QPixmap m_originalPxr;
QColor m_fillColor;
QColor m_shapeColor;
QColor m_fillMask;
QColor m_shapeMask;
QString m_tip;
int m_iconsize;
CCurveEditor& m_CurveEditor;
SCurveEditorCurve& m_Curve;
SCurveEditorKey& m_Key;
int m_VisualSize;
int m_ClickableSize;
CCurveEditorTangentControl* m_pInTangent;
CCurveEditorTangentControl* m_pOutTangent;
};
class EDITOR_COMMON_API CCurveEditorTangentControl
{
public:
CCurveEditorTangentControl(CCurveEditorControl& curveControl, ETangent tangentDirection);
~CCurveEditorTangentControl();
CCurveEditorControl& GetControl();
ETangent GetTangentDirection() const;
bool IsVisible() const;
void SetVisible(bool visible);
bool IsSelected() const;
void SetSelected(bool selected);
void SetVisualSize(int visualSize);
void SetClickableSize(int clickableSize);
void SetDistanceFromControl(int distanceFromControl);
void Paint(QPainter& painter, const QPalette& palette);
bool IsMouseWithinControl(QPointF screenPos) const;
private:
QPointF GetScreenPosition() const;
CCurveEditorControl& m_Control;
ETangent m_TangentDirection;
bool m_Selected;
int m_VisualSize;
int m_ClickableSize;
int m_DistanceFromControl;
bool m_Visible;
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,154 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "CurveEditorContent.h"
#include <QWidget>
#include <Range.h>
#include <AnimTime.h>
class QToolBar;
enum ECurveEditorCurveType
{
eCECT_Bezier,
// 2D Bezier curves are used for better curve control, the editor
// will enforce that the resulting curve is always 1D.
eCECT_2DBezier,
};
namespace CurveEditorHelpers
{
// Picks a nice color value for a curve. Wraps around after 4.
EDITOR_COMMON_API ColorB GetCurveColor(const uint n);
}
class EDITOR_COMMON_API CCurveEditor
: public QWidget
{
Q_OBJECT
public:
CCurveEditor(QWidget* parent);
~CCurveEditor();
void SetContent(SCurveEditorContent* pContent);
SCurveEditorContent* Content() const { return m_pContent; }
SAnimTime Time() const { return m_time; }
void SetTime(const SAnimTime time);
// The background in the time and value range will be drawn a bit brighter to indicate where keys
// should be placed. The curve editor does not enforce that the curves actually stay in those ranges.
void SetTimeRange(const SAnimTime start, const SAnimTime end);
void SetValueRange(const float min, const float max);
void ZoomToTimeRange(const float start, const float end);
void ZoomToValueRange(const float min, const float max);
void SetCurveType(ECurveEditorCurveType curveType);
void SetWeighted(bool bWeighted);
void SetHandlesVisible(bool bVisible);
void SetRulerVisible(bool bVisible);
void SetTimeSliderVisible(bool bVisible);
void SetGridVisible(bool bVisible);
void SetFrameRate(SAnimTime::EFrameRate frameRate) { m_frameRate = frameRate; }
void SetTimeSnapping(bool snapTime) { m_bSnapTime = snapTime; }
void SetKeySnapping(bool snapKeys) { m_bSnapKeys = snapKeys; }
// Tools added to tool bar depend on options above
void FillWithCurveToolsAndConnect(QToolBar* pToolBar);
void paintEvent(QPaintEvent* pEvent) override;
void mousePressEvent(QMouseEvent* pEvent) override;
void mouseDoubleClickEvent(QMouseEvent* pEvent) override;
void mouseMoveEvent(QMouseEvent* pEvent) override;
void mouseReleaseEvent(QMouseEvent* pEvent) override;
void focusOutEvent(QFocusEvent* pEvent) override;
void wheelEvent(QWheelEvent* pEvent) override;
void keyPressEvent(QKeyEvent* pEvent) override;
signals:
void SignalContentChanged();
void SignalScrub();
public slots:
void OnDeleteSelectedKeys();
void OnSetSelectedKeysTangentAuto();
void OnSetSelectedKeysInTangentZero();
void OnSetSelectedKeysInTangentStep();
void OnSetSelectedKeysInTangentLinear();
void OnSetSelectedKeysOutTangentZero();
void OnSetSelectedKeysOutTangentStep();
void OnSetSelectedKeysOutTangentLinear();
void OnFitCurvesHorizontally();
void OnFitCurvesVertically();
void OnBreakTangents();
void OnUnifyTangents();
private:
struct SMouseHandler;
struct SSelectionHandler;
struct SPanHandler;
struct SZoomHandler;
struct SMoveHandler;
struct SHandleMoveHandler;
struct SScrubHandler;
enum ETangent;
void DrawGrid(QPainter& painter, const QPalette& palette);
void LeftButtonMousePressEvent(QMouseEvent* pEvent);
void MiddleButtonMousePressEvent(QMouseEvent* pEvent);
void RightButtonMousePressEvent(QMouseEvent* pEvent);
void SelectInRect(const QRect& rect);
void ContentChanged();
void DeleteMarkedKeys();
std::pair<SCurveEditorCurve*, Vec2> HitDetectCurve(const QPoint point);
std::pair<SCurveEditorCurve*, SCurveEditorKey*> HitDetectKey(const QPoint point);
std::tuple<SCurveEditorCurve*, SCurveEditorKey, SCurveEditorKey*, ETangent> HitDetectHandle(const QPoint point);
Vec2 ClosestPointOnCurve(const Vec2 point, const SCurveEditorCurve& curve, const ECurveEditorCurveType curveType);
void AddPointToCurve(Vec2 point, SCurveEditorCurve* pCurve);
void SortKeys(SCurveEditorCurve& curve);
QRect GetCurveArea();
enum ETangent
{
ETangent_In,
ETangent_Out
};
void SetSelectedKeysTangentType(const ETangent tangent, const SBezierControlPoint::ETangentType type);
SCurveEditorContent* m_pContent;
std::unique_ptr<SMouseHandler> m_pMouseHandler;
ECurveEditorCurveType m_curveType;
SAnimTime::EFrameRate m_frameRate;
bool m_bWeighted : 1;
bool m_bHandlesVisible : 1;
bool m_bRulerVisible : 1;
bool m_bTimeSliderVisible : 1;
bool m_bGridVisible : 1;
bool m_bSnapTime : 1;
bool m_bSnapKeys : 1;
SAnimTime m_time;
Vec2 m_zoom;
Vec2 m_translation;
TRange<SAnimTime> m_timeRange;
Range m_valueRange;
};
@@ -0,0 +1,176 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "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();
}
@@ -0,0 +1,52 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#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
@@ -0,0 +1,15 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "../../Editor/Objects/DisplayContextShared.inl"
@@ -0,0 +1,194 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorCommon_precompiled.h"
//Cry
#include <Cry_Camera.h>
//Editor
#include <Util/EditorUtils.h>
#include <Util/Math.h>
//Local
#include "QViewport.h"
#include "DisplayViewportAdapter.h"
CDisplayViewportAdapter::CDisplayViewportAdapter(QViewport* viewport)
: m_viewport(viewport)
{
m_screenMatrix.SetIdentity();
}
void CDisplayViewportAdapter::Update()
{
}
const Matrix34& CDisplayViewportAdapter::GetScreenTM() const
{
return m_screenMatrix;
}
float CDisplayViewportAdapter::GetScreenScaleFactor(const Vec3& position) const
{
float dist = m_viewport->Camera()->GetPosition().GetDistance(position);
if (dist < m_viewport->Camera()->GetNearPlane())
{
dist = m_viewport->Camera()->GetNearPlane();
}
return dist;
}
float CDisplayViewportAdapter::GetScreenScaleFactor([[maybe_unused]] const CCamera& camera, [[maybe_unused]] const Vec3& object_position)
{
return 1;
}
bool CDisplayViewportAdapter::HitTestLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& hitpoint, int pixelRadius, float* pToCameraDistance) const
{
float dist = GetDistanceToLine(lineP1, lineP2, hitpoint);
if (dist <= pixelRadius)
{
if (pToCameraDistance)
{
Vec3 raySrc, rayDir;
ViewToWorldRay(hitpoint, raySrc, rayDir);
Vec3 rayTrg = raySrc + rayDir * 10000.0f;
Vec3 pa, pb;
float mua, mub;
LineLineIntersect(lineP1, lineP2, raySrc, rayTrg, pa, pb, mua, mub);
*pToCameraDistance = mub;
}
return true;
}
return false;
}
float CDisplayViewportAdapter::GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const
{
QPoint p1 = WorldToView(lineP1);
QPoint p2 = WorldToView(lineP2);
return PointToLineDistance2D(
Vec3(float(p1.x()), float(p1.y()), 0),
Vec3(float(p2.x()), float(p2.y()), 0),
Vec3(float(point.x()), float(point.y()), 0));
}
CBaseObjectsCache* CDisplayViewportAdapter::GetVisibleObjectsCache()
{
return 0;
}
bool CDisplayViewportAdapter::IsBoundsVisible([[maybe_unused]] const AABB& box) const
{
return false;
}
void CDisplayViewportAdapter::GetPerpendicularAxis(EAxis* axis, bool* is2D) const
{
*axis = AXIS_NONE;
*is2D = false;
}
const Matrix34& CDisplayViewportAdapter::GetViewTM() const
{
m_viewMatrix = m_viewport->Camera()->GetViewMatrix();
return m_viewMatrix;
}
QPoint CDisplayViewportAdapter::WorldToView(const Vec3& worldPoint) const
{
return m_viewport->ProjectToScreen(worldPoint);
}
QPoint CDisplayViewportAdapter::WorldToViewParticleEditor(const Vec3& worldPoint, [[maybe_unused]] int width, [[maybe_unused]] int height) const
{
return m_viewport->ProjectToScreen(worldPoint);
}
Vec3 CDisplayViewportAdapter::WorldToView3D([[maybe_unused]] const Vec3& worldPoint, [[maybe_unused]] int flags) const
{
return Vec3(0.0f, 0.0f, 0.0f);
}
Vec3 CDisplayViewportAdapter::ViewToWorld([[maybe_unused]] const QPoint& vp, [[maybe_unused]] bool* collideWithTerrain, [[maybe_unused]] bool onlyTerrain, [[maybe_unused]] bool bSkipVegetation, [[maybe_unused]] bool bTestRenderMesh, [[maybe_unused]] bool* collideWithObject) const
{
return Vec3(0.0f, 0.0f, 0.0f);
}
void CDisplayViewportAdapter::ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const
{
Ray ray;
// this can fail for number of reasons
if (!m_viewport->ScreenToWorldRay(&ray, vp.x(), vp.y()))
{
// return some "safe" default that will not cause FPE
raySrc = m_viewport->Camera()->GetPosition();
rayDir = m_viewport->Camera()->GetViewdir();
// the interface should be changed to accommodate for error
return;
}
raySrc = ray.origin;
rayDir = ray.direction;
}
float CDisplayViewportAdapter::GetGridStep() const
{
return 1.0f;
}
float CDisplayViewportAdapter::GetAspectRatio() const
{
int w, h;
GetDimensions(&w, &h);
if (h != 0)
{
return float(w) / h;
}
else
{
return 1.0f;
}
}
const Plane* CDisplayViewportAdapter::GetConstructionPlane() const
{
return 0;
}
void CDisplayViewportAdapter::ScreenToClient([[maybe_unused]] QPoint& pt) const
{
}
void CDisplayViewportAdapter::GetDimensions(int* width, int* height) const
{
if (width)
{
*width = m_viewport->Width();
}
if (height)
{
*height = m_viewport->Height();
}
}
void CDisplayViewportAdapter::setRay([[maybe_unused]] QPoint& vp, [[maybe_unused]] Vec3& raySrc, [[maybe_unused]] Vec3& rayDir)
{
}
void CDisplayViewportAdapter::setHitcontext([[maybe_unused]] QPoint& vp, [[maybe_unused]] Vec3& raySrc, [[maybe_unused]] Vec3& rayDir)
{
}
@@ -0,0 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
//Cry
#include <Cry_Math.h>
#include "Cry_Matrix34.h"
#include "Cry_Vector3.h"
//Editor
#include "Include/IDisplayViewport.h"
//Local
#include "EditorCommonAPI.h"
class EDITOR_COMMON_API QViewport;
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class EDITOR_COMMON_API CDisplayViewportAdapter
: public ::IDisplayViewport
{
public:
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
CDisplayViewportAdapter(QViewport* viewport);
void Update() override;
const Matrix34& GetScreenTM() const override;
float GetScreenScaleFactor(const Vec3& position) const override;
float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position) override;
bool HitTestLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& hitpoint, int pixelRadius, float* pToCameraDistance = 0) const override;
float GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const override;
CBaseObjectsCache* GetVisibleObjectsCache() override;
bool IsBoundsVisible(const AABB& box) const override;
void GetPerpendicularAxis(EAxis* axis, bool* is2D) const override;
const Matrix34& GetViewTM() const override;
QPoint WorldToView(const Vec3& worldPoint) const override;
QPoint WorldToViewParticleEditor(const Vec3& worldPoint, int width, int height) const override;
Vec3 WorldToView3D(const Vec3& worldPoint, int flags = 0) const override;
Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override;
void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override;
float GetGridStep() const override;
float GetAspectRatio() const override;
const Plane* GetConstructionPlane() const override;
void ScreenToClient(QPoint& pt) const override;
void GetDimensions(int* width, int* height) const override;
void setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override;
void setHitcontext(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override;
private:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
mutable Matrix34 m_viewMatrix;
Matrix34 m_screenMatrix;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
QViewport* m_viewport;
};
@@ -0,0 +1,234 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "DockTitleBarWidget.h"
#include <QStyle>
#include <QStyleOptionToolButton>
#include <AzCore/Casting/numeric_cast.h>
static 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));
}
class CDockWidgetTitleButton
: public QAbstractButton
{
public:
CDockWidgetTitleButton(QWidget* parent);
QSize sizeHint() const;
QSize minimumSizeHint() const { return sizeHint(); }
protected:
void enterEvent(QEvent* ev);
void leaveEvent(QEvent* ev);
void paintEvent(QPaintEvent* ev);
};
class CTitleBarText
: public QWidget
{
public:
CTitleBarText(QWidget* parent, QDockWidget* dockWidget)
: QWidget(parent)
, m_dockWidget(dockWidget)
{
QFont font;
font.setBold(true);
setFont(font);
}
void paintEvent([[maybe_unused]] QPaintEvent* ev) override
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, true);
QRect r = rect().adjusted(2, 2, -3, -3);
p.translate(0.5f, 0.5f);
QColor color = Interpolate(palette().color(QPalette::Window), palette().color(QPalette::Shadow), 0.2f);
p.setBrush(QBrush(color));
p.setPen(Qt::NoPen);
p.drawRoundedRect(r, 4, 4, Qt::AbsoluteSize);
p.setPen(QPen(palette().color(QPalette::WindowText)));
QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
textOption.setWrapMode(QTextOption::NoWrap);
p.drawText(r.adjusted(4, 0, 0, 0), m_dockWidget->windowTitle(), textOption);
}
private:
QDockWidget* m_dockWidget;
};
// ---------------------------------------------------------------------------
CDockWidgetTitleButton::CDockWidgetTitleButton(QWidget* parent)
: QAbstractButton(parent)
{
setFocusPolicy(Qt::NoFocus);
}
QSize CDockWidgetTitleButton::sizeHint() const
{
ensurePolished();
int size = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this);
if (!icon().isNull())
{
int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
QSize sz = icon().actualSize(QSize(iconSize, iconSize));
size += qMax(sz.width(), sz.height());
}
return QSize(size, size);
}
void CDockWidgetTitleButton::enterEvent(QEvent* ev)
{
if (isEnabled())
{
update();
}
QAbstractButton::enterEvent(ev);
}
void CDockWidgetTitleButton::leaveEvent(QEvent* ev)
{
if (isEnabled())
{
update();
}
QAbstractButton::leaveEvent(ev);
}
void CDockWidgetTitleButton::paintEvent([[maybe_unused]] QPaintEvent* ev)
{
QPainter painter(this);
QStyleOptionToolButton opt;
opt.state = QStyle::State_AutoRaise;
opt.init(this);
opt.state |= QStyle::State_AutoRaise;
if (isEnabled() && underMouse() && !isChecked() && !isDown())
{
opt.state |= QStyle::State_Raised;
}
if (isChecked())
{
opt.state |= QStyle::State_On;
}
if (isDown())
{
opt.state |= QStyle::State_Sunken;
}
if (opt.state & (QStyle::State_Raised | QStyle::State_Sunken))
{
style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter, this);
}
opt.icon = icon();
opt.subControls = QStyle::SubControls();
opt.activeSubControls = QStyle::SubControls();
opt.features = QStyleOptionToolButton::None;
opt.arrowType = Qt::NoArrow;
int size = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
opt.iconSize = QSize(size, size);
style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &painter, this);
}
// ---------------------------------------------------------------------------
CDockTitleBarWidget::CDockTitleBarWidget(QDockWidget* dockWidget)
: m_dockWidget(dockWidget)
{
CTitleBarText* textWidget = new CTitleBarText(this, dockWidget);
m_layout = new QBoxLayout(QBoxLayout::LeftToRight);
m_layout->setContentsMargins(0, 0, 0, 0);
m_layout->setSpacing(0);
m_layout->addWidget(textWidget, 1);
QStyleOptionDockWidget opt;
opt.initFrom(dockWidget);
opt.closable = dockWidget->features() & QDockWidget::DockWidgetClosable;
opt.movable = dockWidget->features() & QDockWidget::DockWidgetMovable;
opt.floatable = dockWidget->features() & QDockWidget::DockWidgetFloatable;
m_buttonLayout = new QBoxLayout(QBoxLayout::LeftToRight);
m_buttonLayout->setContentsMargins(0, 0, 0, 0);
m_buttonLayout->setSpacing(0);
m_layout->addLayout(m_buttonLayout, 0);
m_floatButton = new CDockWidgetTitleButton(dockWidget);
m_floatButton->setIcon(QIcon("Editor/Icons/float.png"));
m_floatButton->setVisible(opt.floatable);
m_floatButton->setToolTip("Toggle Floating");
connect(m_floatButton, SIGNAL(clicked()), SLOT(OnFloatButtonPressed()));
m_layout->addWidget(m_floatButton, 0);
m_closeButton = new CDockWidgetTitleButton(dockWidget);
// close.png is a standard icon that looks similar to one in Fusion theme but
// uses alpha so it can be used on dark theme as well.
// style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, dockWidget)
QIcon closeIcon("Editor/Icons/close.png");
m_closeButton->setIcon(closeIcon);
m_closeButton->setVisible(opt.closable);
m_closeButton->setToolTip("Close");
connect(m_closeButton, SIGNAL(clicked()), SLOT(OnCloseButtonPressed()));
m_layout->addWidget(m_closeButton, 0);
setLayout(m_layout);
}
void CDockTitleBarWidget::AddCustomButton(const QIcon& icon, const char* tooltip, int id)
{
SCustomButton slot;
slot.button = new CDockWidgetTitleButton(m_dockWidget);
slot.button->setIcon(icon);
slot.button->setToolTip(tooltip);
connect(slot.button, SIGNAL(clicked()), SLOT(OnCustomButtonPressed()));
slot.id = id;
m_buttonLayout->addWidget(slot.button, 0);
m_customButtons.push_back(slot);
}
void CDockTitleBarWidget::OnFloatButtonPressed()
{
m_dockWidget->setFloating(!m_dockWidget->isFloating());
}
void CDockTitleBarWidget::OnCloseButtonPressed()
{
m_dockWidget->close();
}
void CDockTitleBarWidget::OnCustomButtonPressed()
{
QObject* button = sender();
for (size_t i = 0; i < m_customButtons.size(); ++i)
{
if (button == m_customButtons[i].button)
{
SignalCustomButtonPressed(m_customButtons[i].id);
break;
}
}
}
#include <moc_DockTitleBarWidget.cpp>
@@ -0,0 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#if !defined(Q_MOC_RUN)
#include "EditorCommonAPI.h"
#include <QAbstractButton>
#include <QWidget>
#include <QPainter>
#include <QDockWidget>
#include <QBoxLayout>
#include <vector>
#endif
class EDITOR_COMMON_API CDockTitleBarWidget
: public QWidget
{
Q_OBJECT
public:
CDockTitleBarWidget(QDockWidget* dockWidget);
QSize sizeHint() const override
{
QFontMetrics fm(font());
return QSize(40, fm.height() + 8);
}
void AddCustomButton(const QIcon& icon, const char* tooltip, int id);
signals:
void SignalCustomButtonPressed(int id);
private slots:
void OnCloseButtonPressed();
void OnFloatButtonPressed();
void OnCustomButtonPressed();
private:
QDockWidget* m_dockWidget;
QBoxLayout* m_layout;
QBoxLayout* m_buttonLayout;
QAbstractButton* m_floatButton;
QAbstractButton* m_closeButton;
struct SCustomButton
{
int id;
QAbstractButton* button;
};
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
std::vector<SCustomButton> m_customButtons;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
@@ -0,0 +1,196 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "Ruler.h"
#include <QPainter>
#include <QPalette>
#include <AzCore/Casting/numeric_cast.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 = 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 = 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, Interpolate(palette.color(QPalette::Button), palette.color(QPalette::Midlight), 0.25f));
if (options.m_drawBackgroundCallback)
{
options.m_drawBackgroundCallback();
}
QColor midDark = 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] = "";
sprintf_s(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));
}
}
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#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);
}
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "TimeSlider.h"
#include <QPainter>
#include <QPalette>
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);
}
}
@@ -0,0 +1,35 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#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);
}
@@ -0,0 +1,40 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorCommon_precompiled.h"
#include <platform.h>
#include "EditorCommon.h"
#include "EditorCommonAPI.h"
CEditorCommonApp::CEditorCommonApp()
{
}
void EDITOR_COMMON_API InitializeEditorCommon([[maybe_unused]] IEditor* editor)
{
}
void EDITOR_COMMON_API UninitializeEditorCommon()
{
}
void EDITOR_COMMON_API InitializeEditorCommonISystem(ISystem* pSystem)
{
ModuleInitISystem(pSystem, "EditorCommon");
}
void EDITOR_COMMON_API UninitializeEditorCommonISystem(ISystem* pSystem)
{
ModuleShutdownISystem(pSystem);
}
@@ -0,0 +1,6 @@
; EditorCommon.def : Declares the module parameters for the DLL.
LIBRARY
EXPORTS
; Explicit exports can go here
@@ -0,0 +1,22 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#ifndef CRYINCLUDE_EDITORCOMMON_EDITORCOMMON_H
#define CRYINCLUDE_EDITORCOMMON_EDITORCOMMON_H
class CEditorCommonApp
{
public:
CEditorCommonApp();
};
#endif // CRYINCLUDE_EDITORCOMMON_EDITORCOMMON_H
@@ -0,0 +1,15 @@
<RCC>
<qresource>
<file>Icons/CurveEditor/auto.png</file>
<file>Icons/CurveEditor/fit_horizontal.png</file>
<file>Icons/CurveEditor/fit_vertical.png</file>
<file>Icons/CurveEditor/linear_in.png</file>
<file>Icons/CurveEditor/linear_out.png</file>
<file>Icons/CurveEditor/step_in.png</file>
<file>Icons/CurveEditor/step_out.png</file>
<file>Icons/CurveEditor/zero_in.png</file>
<file>Icons/CurveEditor/zero_out.png</file>
<file>Icons/CurveEditor/break.png</file>
<file>Icons/CurveEditor/unify.png</file>
</qresource>
</RCC>
Binary file not shown.
@@ -0,0 +1,43 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#ifndef CRYINCLUDE_EDITORCOMMON_EDITORCOMMONAPI_H
#define CRYINCLUDE_EDITORCOMMON_EDITORCOMMONAPI_H
#include <AzCore/PlatformDef.h>
#if defined(EDITOR_COMMON_EXPORTS)
#define EDITOR_COMMON_API AZ_DLL_EXPORT
#elif defined(EDITOR_COMMON_IMPORTS)
#define EDITOR_COMMON_API AZ_DLL_IMPORT
#else
#define EDITOR_COMMON_API
#endif
struct IEditor;
struct ISystem;
void EDITOR_COMMON_API InitializeEditorCommon(IEditor* editor);
void EDITOR_COMMON_API UninitializeEditorCommon();
void EDITOR_COMMON_API InitializeEditorCommonISystem(ISystem* pSystem);
void EDITOR_COMMON_API UninitializeEditorCommonISystem(ISystem* pSystem);
#endif // CRYINCLUDE_EDITORCOMMON_EDITORCOMMONAPI_H
@@ -0,0 +1,26 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN
#endif
// These redicilous dependencies are needed just to be able to use
// Sandbox gizmos drawing and hit-testing code =(
#include "ISystem.h"
#include "Include/EditorCoreAPI.h"
#include "Util/EditorUtils.h"
@@ -0,0 +1,144 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "EventManager.h"
#include "Serialization/JSONIArchive.h"
#include "Serialization/JSONOArchive.h"
CEventManager* CEventManager::ms_pEventManager;
CEventManager::CEventManager()
: m_nextAddress(0)
, m_nextHandlerId(0)
{
if (ms_pEventManager)
{
CryFatalError("There should be only one event manager instance");
}
ms_pEventManager = this;
}
void CEventManager::Init([[maybe_unused]] SSystemGlobalEnvironment* env)
{
}
CEventManager* CEventManager::GetInstance()
{
return ms_pEventManager;
}
uint CEventManager::GetAddressId(const char* name)
{
auto findIter = m_nameToAddressMap.find(name);
if (findIter != m_nameToAddressMap.end())
{
return findIter->second;
}
uint newId = m_nextAddress++;
m_nameToAddressMap[name] = newId;
return newId;
}
uint CEventManager::GetUniqueAddressId()
{
return m_nextAddress++;
}
void CEventManager::SendEventRaw(const uint address, const char* eventName, const char* message) const
{
SendEventImplementation(address, eventName, message, DynArray<uint>());
}
void CEventManager::SendEventRaw(const uint address, const char* eventName, const char* message, const DynArray<uint>& excludedHandlers) const
{
SendEventImplementation(address, eventName, message, excludedHandlers);
}
void CEventManager::SendEventImplementation(const uint address, const string& eventName, const string& message, const DynArray<uint>& excludedHandlers) const
{
auto handlerFindIter = m_messageRoutingMap.find(std::make_pair(address, eventName));
if (handlerFindIter != m_messageRoutingMap.end())
{
const std::vector<std::pair<uint, TEventHandlerFunc> >& handlers = handlerFindIter->second;
for (uint i = 0; i < handlers.size(); ++i)
{
if (!stl::find(excludedHandlers, handlers[i].first))
{
handlers[i].second(message);
}
}
}
}
bool CEventManager::CanDeliverRaw(const uint address, const char* eventName) const
{
auto handlerFindIter = m_messageRoutingMap.find(std::make_pair(address, eventName));
if (handlerFindIter != m_messageRoutingMap.end())
{
const std::vector<std::pair<uint, TEventHandlerFunc> >& handlers = handlerFindIter->second;
return !handlers.empty();
}
return false;
}
CEventConnection CEventManager::AddEventCallbackRaw(const uint address, const char* eventName, TEventHandlerFunc callback)
{
const uint handlerId = m_nextHandlerId++;
m_messageRoutingMap[std::make_pair(address, eventName)].push_back(std::make_pair(handlerId, callback));
return CEventConnection(address, eventName, handlerId);
}
string CEventManager::SerializeMessageToJSON(const Serialization::SStruct& ref) const
{
Serialization::JSONOArchive oArchive;
oArchive(ref);
return oArchive.buffer();
}
void CEventManager::DeserializeFromJSON(const Serialization::SStruct& ref, const string& json)
{
Serialization::JSONIArchive iArchive;
if (iArchive.open(json.data(), json.size()))
{
iArchive(ref);
}
}
void CEventConnection::Disconnect()
{
if (m_bConnected)
{
auto& messageMap = CEventManager::GetInstance()->m_messageRoutingMap;
auto findIter = messageMap.find(std::make_pair(m_address, m_eventName));
if (findIter != messageMap.end())
{
stl::find_and_erase_if(findIter->second, [=](const std::pair<uint, CEventManager::TEventHandlerFunc>& h)
{
return h.first == m_handlerId;
});
}
if (findIter->second.empty())
{
messageMap.erase(findIter);
}
Reset();
}
}
@@ -0,0 +1,204 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
#define CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
#pragma once
#include "platform.h"
#include "EditorCommonAPI.h"
#include "IEditor.h"
#include "Serialization/IArchive.h"
struct SSystemGlobalEnvironment;
class CEventConnection
{
friend class CEventManager;
friend class CScopedEventConnection;
public:
CEventConnection()
: m_bConnected(false) {}
EDITOR_COMMON_API void Disconnect();
uint GetHandlerId() const { return m_handlerId; }
private:
CEventConnection(const uint address, const string& eventName, const uint handlerId)
: m_address(address)
, m_eventName(eventName)
, m_handlerId(handlerId)
, m_bConnected(true) {}
void Reset()
{
m_bConnected = false;
m_address = 0;
m_handlerId = 0;
m_eventName.clear();
}
void Move(CEventConnection& other)
{
m_bConnected = other.m_bConnected;
m_address = other.m_address;
m_handlerId = other.m_handlerId;
m_eventName.swap(other.m_eventName);
other.Reset();
}
bool m_bConnected;
uint m_address;
uint m_handlerId;
string m_eventName;
};
class CScopedEventConnection
: public CEventConnection
{
public:
CScopedEventConnection()
: CEventConnection() {}
CScopedEventConnection(CScopedEventConnection&& connection)
{
Move(connection);
}
CScopedEventConnection(CEventConnection&& connection)
{
Move(connection);
}
CScopedEventConnection& operator =(CEventConnection&& connection)
{
if (&connection != this)
{
Disconnect();
Move(connection);
}
return *this;
}
~CScopedEventConnection() { Disconnect(); }
private:
CScopedEventConnection(const CScopedEventConnection&); // no implementation
CScopedEventConnection& operator =(const CScopedEventConnection&); // no implementation
};
class EDITOR_COMMON_API CEventManager
{
friend class CEventConnection;
public:
CEventManager();
static CEventManager* GetInstance();
void Init(SSystemGlobalEnvironment* pEnv);
// Registers an address and returns its ID. Multiple event handlers can listen to the same address, allowing broadcasts.
uint GetAddressId(const char* name);
// Registers a new unique address
uint GetUniqueAddressId();
public:
// Sends an event to an address
//
// TMessageType must be a serializable struct
//
template <class TMessageType>
void SendEvent(const uint address, const TMessageType& message)
{
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
SendEventRaw(address, TMessageType::GetName(), json);
}
template <class TMessageType>
void SendEvent(const uint address, const TMessageType& message, const DynArray<uint>& excludedHandlers) const
{
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
SendEventRaw(address, TMessageType::GetName(), json, excludedHandlers);
}
// For sending a raw JSON message.
void SendEventRaw(const uint address, const char* eventName, const char* message) const;
void SendEventRaw(const uint address, const char* eventName, const char* message, const DynArray<uint>& excludedHandlers) const;
// Tests if a call to SendEvent would actually send a message (there is someone listening to this message)
bool CanDeliverRaw(const uint address, const char* eventName) const;
template<class TMessageType>
bool CanDeliver(const uint address) const
{
const char* pEventName = TMessageType::GetName();
return CanDeliverRaw(address, pEventName);
}
// This should be the most common way to add an event callback
//
// This example will install an event handler for OnEvent(const SMessageType &message) that is sent to a specific address:
// CEventManager::GetInstance()->AddEventCallback(componentId, this, &CEventHandler::OnEvent);
//
// TMessageType must be a serializable struct
//
// Returns a CEventConnection. The callback is removed when this object is destroyed.
//
template <class TClassType, class TMessageType>
CEventConnection AddEventCallback(const uint address, TClassType* pThis, void (TClassType::* pMethod)(const TMessageType&))
{
return AddEventCallback<TMessageType>(address, std::bind(pMethod, pThis, std::placeholders::_1));
}
// Same as above, but you can pass in any function object that takes TMessageType& as an argument directly.
//
template <class TMessageType>
CEventConnection AddEventCallback(const uint address, std::function<void (const TMessageType&)> callback)
{
return AddEventCallbackRaw(address, TMessageType::GetName(), [=](const string& json)
{
TMessageType message;
DeserializeFromJSON(Serialization::SStruct(message), json);
callback(message);
});
}
// This can be used if raw parsing of JSON is preferred.
typedef std::function<void (const char*)> TEventHandlerFunc;
CEventConnection AddEventCallbackRaw(const uint componentId, const char* eventName, TEventHandlerFunc callback);
private:
void SendEventImplementation(const uint address, const string& eventName, const string& message, const DynArray<uint>& excludedHandlers) const;
string SerializeMessageToJSON(const Serialization::SStruct& ref) const;
void DeserializeFromJSON(const Serialization::SStruct& ref, const string& json);
uint m_nextAddress;
uint m_nextHandlerId;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
std::map<string, uint, stl::less_stricmp<string> > m_nameToAddressMap;
std::map<std::pair<uint, string>, std::vector<std::pair<uint, TEventHandlerFunc> > > m_messageRoutingMap;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
static CEventManager* ms_pEventManager;
};
#endif // CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3e60156229cc8677e0294d297486f04bd78867ef4e0922b35444c8b45f78584d
size 1090
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd29a16a1d1d9a363e4b154d51910c2cba2787fbbe1360cfd107b393053d2e49
size 1226
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:244005cde119238bbfc2815f36a343c6135c3233d0b72a5c97a6080604568e8f
size 1160
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:33176a8ea6b0798adf1114fdbea4b0f5c708f40c3d48a047b1cb0fa6ebcbbded
size 1181
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c122557745cc377768491ce59c5b5b17e54671aa59f7f87101766aa61758959e
size 939
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c2a360a56a37bfae2bea16b495f5b6ee482caa28d0949e8eadea48fdaae654f
size 845
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:eb0f43228bdb5246ea3bfde0726f07e0df0468279610ba4c801b21e264b33123
size 765
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:97a2e879222323bc70787efbe2cbc1c47bbabb7b10df8465857e600a9084abb2
size 795
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:58e8476b7bec1ed8eddfde3d5228f58fcfba11329318f5dfef3d98eb99f3a897
size 1113
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a7847e8b7f3dd76395d893888916e4bd97ddf3f678d37d19836da04c2923791e
size 871
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:470266956c6911690299f29539c400122ae707f88d9b6ba3516faf196a8fd571
size 877
@@ -0,0 +1,224 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "Serialization/ClassFactory.h"
#include "Serialization/Pointers.h"
#include "Serialization/IArchive.h"
#include "ListSelectionDialog.h"
#include <IEditor.h>
#include <QDialogButtonBox>
#include <QBoxLayout>
#include <QTreeView>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QIcon>
#include <QMenu>
#include <QEvent>
#include <QKeyEvent>
#include <QCoreApplication>
#include <QByteArray>
#include "IResourceSelectorHost.h"
#include "DeepFilterProxyModel.h"
// ---------------------------------------------------------------------------
ListSelectionDialog::ListSelectionDialog(QWidget* parent)
: QDialog(parent)
, m_currentColumn(0)
{
setWindowTitle("Choose...");
setWindowModality(Qt::ApplicationModal);
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
setLayout(layout);
QBoxLayout* filterBox = new QBoxLayout(QBoxLayout::LeftToRight);
layout->addLayout(filterBox);
{
filterBox->addWidget(new QLabel("Filter:", this), 0);
filterBox->addWidget(m_filterEdit = new QLineEdit(this), 1);
connect(m_filterEdit, SIGNAL(textChanged(const QString&)), this, SLOT(onFilterChanged(const QString&)));
m_filterEdit->installEventFilter(this);
}
QBoxLayout* infoBox = new QBoxLayout(QBoxLayout::LeftToRight);
layout->addLayout(infoBox);
m_model = new QStandardItemModel();
m_model->setColumnCount(1);
m_model->setHeaderData(0, Qt::Horizontal, "Name", Qt::DisplayRole);
m_filterModel = new DeepFilterProxyModel(this);
m_filterModel->setSourceModel(m_model);
m_filterModel->setDynamicSortFilter(true);
m_tree = new QTreeView(this);
//m_tree->setColumnCount(3);
m_tree->setModel(m_filterModel);
m_tree->header()->setStretchLastSection(false);
#if QT_VERSION >= 0x50000
m_tree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
#else
m_tree->header()->setResizeMode(0, QHeaderView::Stretch);
#endif
//m_tree->header()->resizeSection(0, 80);
connect(m_tree, SIGNAL(activated(const QModelIndex&)), this, SLOT(onActivated(const QModelIndex&)));
layout->addWidget(m_tree, 1);
QDialogButtonBox* buttons = new QDialogButtonBox(this);
buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
layout->addWidget(buttons, 0);
}
bool ListSelectionDialog::eventFilter(QObject* obj, QEvent* event)
{
if (obj == m_filterEdit && event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = (QKeyEvent*)event;
if (keyEvent->key() == Qt::Key_Down ||
keyEvent->key() == Qt::Key_Up ||
keyEvent->key() == Qt::Key_PageDown ||
keyEvent->key() == Qt::Key_PageUp)
{
QCoreApplication::sendEvent(m_tree, event);
return true;
}
}
return QDialog::eventFilter(obj, event);
}
void ListSelectionDialog::onFilterChanged(const QString& str)
{
m_filterModel->setFilterString(str);
m_filterModel->invalidate();
m_tree->expandAll();
QModelIndex currentSource = m_filterModel->mapToSource(m_tree->selectionModel()->currentIndex());
if (!currentSource.isValid() || !m_filterModel->matchFilter(currentSource.row(), currentSource.parent()))
{
QModelIndex firstMatchingIndex = m_filterModel->findFirstMatchingIndex(QModelIndex());
if (firstMatchingIndex.isValid())
{
m_tree->selectionModel()->setCurrentIndex(firstMatchingIndex, QItemSelectionModel::SelectCurrent);
}
}
}
void ListSelectionDialog::onActivated(const QModelIndex& index)
{
m_tree->setCurrentIndex(index);
accept();
}
QSize ListSelectionDialog::sizeHint() const
{
return QSize(600, 900);
}
void ListSelectionDialog::SetColumnText(int column, const char* text)
{
if (column >= m_model->columnCount())
{
int oldColumnCount = m_model->columnCount();
m_model->setColumnCount(column + 1);
for (int i = oldColumnCount; i <= column; ++i)
{
#if QT_VERSION >= 0x50000
m_tree->header()->setSectionResizeMode(i, QHeaderView::Interactive);
#else
m_tree->header()->setResizeMode(i, QHeaderView::Interactive);
#endif
m_tree->header()->resizeSection(i, 40);
}
}
m_model->setHeaderData(column, Qt::Horizontal, text, Qt::DisplayRole);
}
void ListSelectionDialog::SetColumnWidth(int column, int width)
{
if (column >= m_model->columnCount())
{
return;
}
m_tree->header()->resizeSection(column, width);
}
void ListSelectionDialog::AddRow(const char* name)
{
AddRow(name, QIcon());
}
void ListSelectionDialog::AddRow(const char* name, const QIcon& icon)
{
QStandardItem* item = new QStandardItem(name);
item->setEditable(false);
item->setData(name);
item->setIcon(icon);
QList<QStandardItem*> items;
items.append(item);
m_model->appendRow(items);
m_currentColumn = 1;
m_firstColumnToItem[name] = item;
}
void ListSelectionDialog::AddRowColumn(const char* text)
{
int itemCount = m_model->rowCount(QModelIndex());
if (itemCount == 0)
{
return;
}
QStandardItem* item = new QStandardItem();
item->setText(QString::fromLocal8Bit(text));
if (QStandardItem* lastItem = m_model->item(itemCount - 1, 0))
{
item->setData(lastItem->data());
}
item->setEditable(false);
m_model->setItem(itemCount - 1, m_currentColumn, item);
++m_currentColumn;
}
QString ListSelectionDialog::ChooseItem(const QString& currentValue)
{
m_tree->expandAll();
if (exec() == QDialog::Accepted && m_tree->selectionModel()->currentIndex().isValid())
{
QModelIndex currentIndex = m_tree->selectionModel()->currentIndex();
QModelIndex sourceCurrentIndex = m_filterModel->mapToSource(currentIndex);
QStandardItem* item = m_model->itemFromIndex(sourceCurrentIndex);
if (item)
{
m_chosenItem = item->data().toString().toUtf8();
return m_chosenItem.constData();
}
}
return currentValue;
}
// ---------------------------------------------------------------------------
#include <moc_ListSelectionDialog.cpp>
@@ -0,0 +1,73 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_LISTSELECTIONDIALOG_H
#define CRYINCLUDE_EDITORCOMMON_LISTSELECTIONDIALOG_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "EditorCommonAPI.h"
#include <QDialog>
#include <QMap>
#endif
class DeepFilterProxyModel;
class QLineEdit;
class QModelIndex;
class QStandardItemModel;
class QStandardItem;
class QString;
class QTreeView;
class QWidget;
class QByteArray;
class EDITOR_COMMON_API ListSelectionDialog
: public QDialog
{
Q_OBJECT
public:
ListSelectionDialog(QWidget* parent);
void SetColumnText(int column, const char* text);
void SetColumnWidth(int column, int width);
void AddRow(const char* firstColumnValue);
void AddRow(const char* firstColumnValue, const QIcon& icon);
void AddRowColumn(const char* value);
QString ChooseItem(const QString& currentValue);
QSize sizeHint() const override;
protected slots:
void onActivated(const QModelIndex& index);
void onFilterChanged(const QString&);
protected:
bool eventFilter(QObject* obj, QEvent* event);
private:
QTreeView* m_tree;
QStandardItemModel* m_model;
DeepFilterProxyModel* m_filterModel;
typedef QMap<QString, QStandardItem*> StringToItem;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
StringToItem m_firstColumnToItem;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
QLineEdit* m_filterEdit;
QByteArray m_chosenItem;
int m_currentColumn;
};
#endif // CRYINCLUDE_EDITORCOMMON_LISTSELECTIONDIALOG_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,336 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_MANIPSCENE_H
#define CRYINCLUDE_EDITORCOMMON_MANIPSCENE_H
#pragma once
#include <platform.h>
#include <Cry_Geo.h>
#include <Cry_Color.h>
#include "EditorCommonAPI.h"
#include <QObject>
#include "QViewportConsumer.h"
namespace Serialization {
class IArchive;
}
class CAxisHelper;
// Manip is a set of reusable utilities for creating interactive 3d scene that
// can be manipulated with gizmos.
namespace Manip
{
using std::unique_ptr;
using std::set;
using std::vector;
enum EElementCaps
{
CAP_SELECT = 1 << 0,
CAP_HIDE = 1 << 1,
CAP_MOVE = 1 << 2,
CAP_ROTATE = 1 << 3,
CAP_SCALE = 1 << 4,
CAP_DELETE = 1 << 5,
};
enum EElementShape
{
SHAPE_AXES,
SHAPE_BOX
};
enum EElementAction
{
ACTION_NONE,
ACTION_DELETE,
ACTION_HIDE,
ACTION_UNHIDE
};
enum EElementColorGroup
{
ELEMENT_COLOR_PROXY,
ELEMENT_COLOR_CLOTH
};
struct SElementPlacement
{
QuatT transform;
QuatT startTransform;
Vec3 center;
Vec3 size;
SElementPlacement()
: transform(IDENTITY)
, startTransform(IDENTITY)
, size(1.0f, 1.0f, 1.0f)
, center(0.0f, 0.0f, 0.0f)
{}
void Serialize(Serialization::IArchive& ar);
};
typedef uint64 ElementId;
struct SSpaceAndIndex
{
int m_space;
int m_jointCRC32;
int m_attachmentCRC32;
SSpaceAndIndex()
{
m_space = -1;
m_jointCRC32 = -1;
m_attachmentCRC32 = -1;
};
};
struct SElement
{
int id;
union
{
int originalId;
const void* originalHandle;
};
int layer;
SElementPlacement placement;
int caps;
EElementAction action;
EElementShape shape;
EElementColorGroup colorGroup;
SSpaceAndIndex parentSpaceIndex;
SSpaceAndIndex parentOrientationSpaceIndex;
QuatT parentSpaceConcatenation;
int mousePickPriority;
bool hidden;
bool changed;
bool alwaysXRay;
SElement()
: id()
, layer(0)
, originalHandle(0)
, action(ACTION_NONE)
, shape(SHAPE_AXES)
, hidden(false)
, changed(false)
, colorGroup(ELEMENT_COLOR_PROXY)
, mousePickPriority(0)
, alwaysXRay(false)
, parentSpaceIndex()
, parentOrientationSpaceIndex()
, parentSpaceConcatenation(IDENTITY)
{
}
};
typedef std::vector<SElement> SElements;
struct SElementData {};
struct IMouseDragHandler
{
virtual ~IMouseDragHandler() = default;
virtual bool Begin(const SMouseEvent& ev, Vec3 hitPoint) = 0;
virtual void Update(const SMouseEvent& ev) = 0;
virtual void Render([[maybe_unused]] const SRenderContext& rc) {}
virtual void End(const SMouseEvent& ev) = 0;
};
struct SSelectionSet
{
SSelectionSet() {}
SSelectionSet(ElementId id) { items.push_back(id); }
void Clear();
void Add(ElementId elementId)
{
items.erase(std::remove(items.begin(), items.end(), elementId), items.end());
items.push_back(elementId);
std::sort(items.begin(), items.end());
}
void Remove(int elementId);
bool IsEmpty() const{ return items.empty(); }
bool Contains(int id) const{ return std::find(items.begin(), items.end(), id) != items.end(); }
size_t Size() const{ return items.size(); }
bool operator==(const SSelectionSet& rhs) const
{
return items == rhs.items;
}
bool operator!=(const SSelectionSet& rhs) const{ return !operator==(rhs); }
std::vector<ElementId> items;
};
struct ICommand {};
struct IElementTracer
{
virtual bool HitRay(Vec3* intersectionPoint, const Ray& ray, const SElement& element) const = 0;
};
struct IElementDrawer
{
virtual bool Draw(const SElement& element);
};
enum ETransformationSpace
{
SPACE_WORLD,
SPACE_LOCAL
};
enum ETransformationMode
{
MODE_TRANSLATE,
MODE_ROTATE,
MODE_SCALE
};
struct SLookSettings
{
ColorB proxyColor;
ColorB proxySelectionColor;
ColorB proxyHighlightColor;
ColorB clothProxyColor;
ColorB jointColor;
ColorB jointHighlightColor;
ColorB jointSelectionColor;
SLookSettings()
: proxyColor(126, 159, 243, 128)
, proxySelectionColor(255, 255, 255, 128)
, proxyHighlightColor(233, 255, 122, 128)
, clothProxyColor(243, 159, 126, 128)
, jointColor(0, 249, 48, 255)
, jointHighlightColor(255, 248, 0, 128)
, jointSelectionColor(255, 255, 255, 128)
{
}
};
struct ISpaceProvider
{
virtual ~ISpaceProvider() = default;
virtual SSpaceAndIndex FindSpaceIndexByName(int spaceType, const char* name, int parentsUp) const = 0;
virtual QuatT GetTransform(const SSpaceAndIndex& index) const = 0;
};
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class EDITOR_COMMON_API CScene
: public QObject
, public QViewportConsumer
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
Q_OBJECT
public:
CScene();
~CScene();
void OnViewportKey(const SKeyEvent& ev) override;
bool ProcessesViewportKey(const QKeySequence& key) override;
void OnViewportMouse(const SMouseEvent& ev) override;
void OnViewportRender(const SRenderContext& rc) override;
void SetTransformationMode(ETransformationMode mode);
ETransformationMode TransformationMode() const;
void SetTransformationSpace(ETransformationSpace space);
ETransformationSpace TransformationSpace() const { return m_transformationSpace; }
void SetVisibleLayerMask(unsigned int layerMask);
unsigned int VisibleLayerMask() const { return m_visibleLayerMask; }
bool IsLayerVisible(int layer) const;
void Clear();
void ClearLayer(int layer);
void AddElement(const SElement& element);
void AddElement(const SElement& element, ElementId id);
void ApplyToAll(EElementAction);
void ApplyToSelection(EElementAction);
void SetSpaceProvider(ISpaceProvider* spaceProvider);
ISpaceProvider* SpaceProvider() const{ return m_spaceProvider; }
QuatT GetParentSpace(const SElement& e) const;
QuatT ElementToWorldSpace(const SElement& e) const;
void WorldSpaceToElement(SElement* e, const QuatT& worldSpaceTransform);
void SetCustomTracer(IElementTracer* tracer);
const SElements& Elements() const{ return m_elements; }
SElements& Elements() { return m_elements; }
void GetSelectedElements(SElements* elements) const;
const SSelectionSet& Selection() const{ return m_selection; }
void SetSelection(const SSelectionSet& selection);
void AddToSelection(const SSelectionSet& selection);
void AddToSelection(ElementId elementId);
bool SelectionCanBeMoved() const;
bool SelectionCanBeRotated() const;
QuatT GetSelectionTransform(ETransformationSpace space) const;
bool SetSelectionTransform(ETransformationSpace space, const QuatT& newTransform);
void Serialize(Serialization::IArchive& ar);
signals:
void SignalUndo();
void SignalRedo();
void SignalPushUndo(const char* description, ICommand* cause);
void SignalElementsChanged(unsigned int layerBits);
void SignalElementContinousChange(unsigned int layerBits);
void SignalPropertiesChanged();
void SignalRenderElements(const SElements& elements, const SRenderContext& rc);
void SignalSelectionChanged();
void SignalManipulationModeChanged();
private:
void UpdateElements(const SElements& elements);
bool SetSelectionTransform(const Matrix34& newMatrix);
Matrix34 GetSelectionTransform() const;
int GetSelectionCaps() const;
Vec3 GetSelectionSize() const;
bool SetSelectionSize(const Vec3& size);
void OnMouseMove(const SMouseEvent& ev);
struct SBlockSelectHandler;
struct SMoveHandler;
struct SRotationHandler;
struct SScalingHandler;
struct STransformBox;
IElementTracer* m_customTracer;
IElementDrawer* m_customDrawer;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
SSelectionSet m_selection;
unique_ptr<IMouseDragHandler> m_mouseDragHandler;
ISpaceProvider* m_spaceProvider;
unique_ptr<CAxisHelper> m_axisHelper;
SElements m_elements;
std::vector<ElementId> m_lastIdByLayer;
ETransformationMode m_transformationMode;
ETransformationSpace m_transformationSpace;
int m_highlightItem;
unsigned int m_visibleLayerMask;
bool m_showGizmo;
SLookSettings m_lookSettings;
int m_highlightedItem;
QuatT m_temporaryLocalDelta;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
}
#endif // CRYINCLUDE_EDITORCOMMON_MANIPSCENE_H
@@ -0,0 +1,29 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates
#include <QPropertyTree/Unicode.h>
#include <vector>
#include <QtCore/QString>
string fromWideChar(const wchar_t* wstr)
{
return QString::fromWCharArray(wstr).toUtf8().data();
}
wstring toWideChar(const char* str)
{
QString s = QString::fromUtf8(str);
std::vector<wchar_t> result(s.size()+1);
s.toWCharArray(&result[0]);
return &result[0];
}
@@ -0,0 +1,14 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(FILES
../Common/UnixLike/QPropertyTree/Unicode_UnixLike.cpp
)
@@ -0,0 +1,14 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(FILES
../Common/UnixLike/QPropertyTree/Unicode_UnixLike.cpp
)
@@ -0,0 +1,41 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates
#include <QPropertyTree/Unicode.h>
#include <AzCore/PlatformIncl.h>
string fromWideChar(const wchar_t* wstr)
{
// We have different implementation for windows as Qt for windows
// is built with wchar_t of diferent size (4 bytes, as on linux).
// Therefore we avoid calling any wchar_t functions in Qt.
const unsigned int codepage = CP_UTF8;
int len = WideCharToMultiByte(codepage, 0, wstr, -1, NULL, 0, 0, 0);
char* buf = (char*)alloca(len);
if (len > 1) {
WideCharToMultiByte(codepage, 0, wstr, -1, buf, len, 0, 0);
return string(buf, len - 1);
}
return string();
}
wstring toWideChar(const char* str)
{
const unsigned int codepage = CP_UTF8;
int len = MultiByteToWideChar(codepage, 0, str, -1, NULL, 0);
wchar_t* buf = (wchar_t*)alloca(len * sizeof(wchar_t));
if (len > 1) {
MultiByteToWideChar(codepage, 0, str, -1, buf, len);
return wstring(buf, len - 1);
}
return wstring();
}
@@ -0,0 +1,14 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
set(FILES
QPropertyTree/Unicode_Windows.cpp
)
@@ -0,0 +1,75 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <QAbstractQVariantTreeDataModel.h>
QAbstractQVariantTreeDataModel::Item* QAbstractQVariantTreeDataModel::itemFromIndex(const QModelIndex& index) const
{
if (index.isValid())
{
return (Item*)index.internalPointer();
}
return m_root.get();
}
QModelIndex QAbstractQVariantTreeDataModel::indexFromItem(QAbstractQVariantTreeDataModel::Item* item, int col /*= 0*/) const
{
if (0 == item)
{
return QModelIndex();
}
if (!item->m_parent || !item->m_parent->asFolder())
{
return QModelIndex();
}
int row = item->m_parent->asFolder()->row(item);
return createIndex(row, col, item);
}
QModelIndex QAbstractQVariantTreeDataModel::index(int row, int column, const QModelIndex& parent /*= QModelIndex()*/) const
{
Item* parentItem = itemFromIndex(parent);
if (parentItem && parentItem->asFolder() && row < parentItem->asFolder()->m_children.size())
{
Item* item = parentItem->asFolder()->m_children[row].get();
return createIndex(row, column, item);
}
return QModelIndex();
}
QModelIndex QAbstractQVariantTreeDataModel::parent(const QModelIndex& child) const
{
Item* item = itemFromIndex(child);
return item && item->m_parent && item->m_parent->asFolder() ? indexFromItem(item->m_parent) : QModelIndex();
}
bool QAbstractQVariantTreeDataModel::hasChildren(const QModelIndex& parent /* = QModelIndex() */) const
{
Item* item = itemFromIndex(parent);
return item && item->asFolder() && item->asFolder()->m_children.size();
}
int QAbstractQVariantTreeDataModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
{
Item* item = itemFromIndex(parent);
int res = 0;
if (item && item->asFolder())
{
res = (int) item->asFolder()->m_children.size();
}
return res;
}
int QAbstractQVariantTreeDataModel::columnCount([[maybe_unused]] const QModelIndex& parent /*= QModelIndex()*/) const
{
return 1;
}
@@ -0,0 +1,87 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#ifndef QABSTRACTQVARIANTTREEDATAMODEL_H
#define QABSTRACTQVARIANTTREEDATAMODEL_H
#include <QAbstractItemModel>
#include <memory>
#include <vector>
#include "EditorCommonAPI.h"
class EDITOR_COMMON_API QAbstractQVariantTreeDataModel
: public QAbstractItemModel
{
public:
QAbstractQVariantTreeDataModel(QObject* parent)
: QAbstractItemModel(parent) { }
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex& child) const override;
bool hasChildren(const QModelIndex& parent = QModelIndex()) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
protected:
struct Folder;
struct Item
{
Item()
: m_parent(0) { }
QMap<int, QVariant> m_data;
Folder* m_parent;
virtual ~Item() = default;
virtual const Folder* asFolder() const { return 0; } // need this as we don't have RTTI
};
struct Folder
: public Item
{
Folder(const QString& name)
{
m_data.insert(Qt::DisplayRole, name);
}
std::vector < std::shared_ptr<Item> > m_children;
const Folder* asFolder() const override { return this; } // need this as we don't have RTTI
int row(Item* item) const
{
for (int i = 0; i < m_children.size(); ++i)
{
if (m_children[i].get() == item)
{
return i;
}
}
return -1;
}
void addChild(std::shared_ptr<Item> item)
{
item->m_parent = this;
m_children.push_back(item);
}
};
Item* itemFromIndex(const QModelIndex& index) const;
QModelIndex indexFromItem(Item* item, int col = 0) const;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
std::shared_ptr<Folder> m_root;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
#endif // QABSTRACTQVARIANTTREEDATAMODEL_H
@@ -0,0 +1,309 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "QParentWndWidget.h"
#include <QEvent>
#include <QGuiApplication>
#include <QApplication>
#include <QFocusEvent>
#include "QParentWndWidget.h"
#include <qt_windows.h>
#if QT_VERSION >= 0x050000
#include <QWindow>
#endif
static HWND FindTopmostWindow(HWND child, bool considerWsChild)
{
if (child == GetDesktopWindow())
{
return 0;
}
HWND current = child;
while (GetParent(current) != 0)
{
if (considerWsChild && (GetWindowLongW(current, GWL_STYLE) & WS_CHILD) == 0)
{
break;
}
current = GetParent(current);
}
return current;
}
QParentWndWidget::QParentWndWidget(HWND parent)
: m_parent(parent)
, m_previousFocus(0)
, m_modalityRoot(0)
, m_parentToCenterOn(0)
{
if (m_parent)
{
SetWindowLongA((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP);
#if QT_VERSION >= 0x50000
QWindow* window = windowHandle();
window->setProperty("_q_embedded_native_parent_handle", (WId)m_parent);
SetParent((HWND)winId(), m_parent);
window->setFlags(Qt::FramelessWindowHint);
#else
SetParent((HWND)winId(), m_parent);
#endif
QEvent e(QEvent::EmbeddingControl);
QApplication::sendEvent(this, &e);
}
m_parentToCenterOn = FindTopmostWindow(m_parent, true);
m_modalityRoot = FindTopmostWindow(m_parent, false);
}
void QParentWndWidget::childEvent(QChildEvent* ev)
{
QObject* child = ev->child();
if (child->isWidgetType())
{
if (ev->added())
{
if (child->isWidgetType())
{
child->installEventFilter(this);
}
}
else if (ev->removed() && m_parentWasDisabled)
{
m_parentWasDisabled = false;
EnableWindow(m_modalityRoot, true);
child->removeEventFilter(this);
}
}
QWidget::childEvent(ev);
}
void QParentWndWidget::show()
{
if (!m_previousFocus)
{
m_previousFocus = ::GetFocus();
}
if (!m_previousFocus)
{
m_previousFocus = parentWindow();
}
QWidget::show();
}
void QParentWndWidget::hide()
{
QWidget::hide();
}
void QParentWndWidget::center()
{
const QWidget* child = findChild<QWidget*>();
RECT rect;
GetWindowRect(m_parentToCenterOn, &rect);
setGeometry((rect.right - rect.left) / 2 + rect.left,
(rect.bottom - rect.top) / 2 + rect.top, 0, 0);
}
#if QT_VERSION >= 0x50000
bool QParentWndWidget::nativeEvent(const QByteArray&, void* message, long* result)
#else
bool QParentWndWidget::winEvent(MSG* msg, long* result)
#endif
{
#if QT_VERSION >= 0x50000
MSG* msg = (MSG*)message;
#endif
if (msg->message == WM_SETFOCUS)
{
Qt::FocusReason reason;
if (::GetKeyState(VK_LBUTTON) < 0 ||
::GetKeyState(VK_RBUTTON) < 0)
{
reason = Qt::MouseFocusReason;
}
else if (::GetKeyState(VK_SHIFT) < 0)
{
reason = Qt::BacktabFocusReason;
}
else
{
reason = Qt::TabFocusReason;
}
QFocusEvent ev(QEvent::FocusIn, reason);
QApplication::sendEvent(this, &ev);
}
if (msg->message == WM_GETDLGCODE)
{
*result = DLGC_WANTARROWS | DLGC_WANTTAB;
return(true);
}
return false;
}
bool QParentWndWidget::eventFilter(QObject* obj, QEvent* ev)
{
QWidget* widget = (QWidget*)obj;
switch (ev->type())
{
case QEvent::WindowDeactivate:
{
if (widget->isModal() && isHidden())
{
BringWindowToTop(m_parent);
}
break;
}
case QEvent::Show:
{
if (widget->isWindow())
{
if (!m_previousFocus)
{
m_previousFocus = ::GetFocus();
}
if (!m_previousFocus)
{
m_previousFocus = parentWindow();
}
hide();
if (widget->isModal() && !m_parentWasDisabled)
{
EnableWindow(m_modalityRoot, false);
m_parentWasDisabled = true;
}
}
break;
}
case QEvent::Hide:
{
if (m_parentWasDisabled)
{
EnableWindow(m_modalityRoot, true);
m_parentWasDisabled = false;
}
if (m_previousFocus)
{
::SetFocus(m_previousFocus);
}
else
{
::SetFocus(parentWindow());
}
if (widget->testAttribute(Qt::WA_DeleteOnClose) && widget->isWindow())
{
deleteLater();
}
break;
}
case QEvent::Close:
{
::SetActiveWindow(m_parent);
if (widget->testAttribute(Qt::WA_DeleteOnClose))
{
deleteLater();
}
break;
}
default:
break;
}
;
return QWidget::eventFilter(obj, ev);
}
void QParentWndWidget::focusInEvent(QFocusEvent* ev)
{
QWidget* candidate = this;
if (ev->reason() == Qt::TabFocusReason || ev->reason() == Qt::BacktabFocusReason)
{
while (candidate && (candidate->focusPolicy() & Qt::TabFocus) == 0)
{
candidate = candidate->nextInFocusChain();
if (candidate == this)
{
candidate = 0;
}
}
if (candidate)
{
candidate->setFocus(ev->reason());
candidate->setAttribute(Qt::WA_KeyboardFocusChange);
candidate->window()->setAttribute(Qt::WA_KeyboardFocusChange);
if (ev->reason() == Qt::BacktabFocusReason)
{
QWidget::focusNextPrevChild(false);
}
}
}
}
bool QParentWndWidget::focusNextPrevChild(bool next)
{
QWidget* current = focusWidget();
if (next)
{
QWidget* nextFocus = current;
while (true)
{
nextFocus = nextFocus->nextInFocusChain();
if (nextFocus->isWindow())
{
break;
}
if (nextFocus->focusPolicy() & Qt::TabFocus)
{
return QWidget::focusNextPrevChild(true);
}
}
}
else
{
if (!current->isWindow())
{
QWidget* nextFocus = current->nextInFocusChain();
QWidget* prevFocus = 0;
QWidget* topLevel = 0;
while (nextFocus != current)
{
if ((nextFocus->focusPolicy() & Qt::TabFocus) != 0)
{
prevFocus = nextFocus;
topLevel = 0;
}
else if (nextFocus->isWindow())
{
topLevel = nextFocus;
}
nextFocus = nextFocus->nextInFocusChain();
}
if (!topLevel)
{
return QWidget::focusNextPrevChild(false);
}
}
}
::SetFocus(m_parent);
return true;
}
#include <moc_QParentWndWidget.cpp>
@@ -0,0 +1,67 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#ifndef CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
#define CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
#if !defined(Q_MOC_RUN)
#include <QWidget>
#include "EditorCommonAPI.h"
#endif
// QParentWndWidget can be used to show Qt popup windows/dialogs on top on
// Win32/MFC windows.
//
// Example of usage:
// QParentWndWidget parent(parentHwnd);
//
// QDialog dialog(parent);
// dialog.exec(...);
class EDITOR_COMMON_API QParentWndWidget
: public QWidget
{
Q_OBJECT
public:
QParentWndWidget(HWND parent);
void show();
void hide();
void center();
HWND parentWindow() const { return m_parent; }
protected:
void childEvent(QChildEvent* e) override;
void focusInEvent(QFocusEvent* ev) override;
bool focusNextPrevChild(bool next) override;
bool eventFilter(QObject* o, QEvent* e) override;
#if QT_VERSION >= 0x50000
bool nativeEvent(const QByteArray&, void* message, long*);
#else
bool winEvent(MSG* msg, long*);
#endif
private:
HWND m_parent;
HWND m_parentToCenterOn;
HWND m_modalityRoot;
HWND m_previousFocus;
bool m_parentWasDisabled;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPARENTWNDWIDGET_H
@@ -0,0 +1,49 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include "EditorCommonAPI.h"
#include "Controls/PropertyCtrl.h"
#include <QtWinMigrate/qwinhost.h>
template<class T>
class TemplatePropertyCtrl
: public QWinHost
{
public:
TemplatePropertyCtrl(QWidget* parent)
: QWinHost(parent) { }
T m_props;
protected:
virtual HWND createWindow(HWND parent, HINSTANCE instance)
{
CWnd* parentWindow = CWnd::FromHandle(parent);
m_props.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), parentWindow /*, IDC_GRAPH_PROPERTIES*/);
m_props.ModifyStyleEx(0, WS_EX_CLIENTEDGE);
m_props.SetParent(parentWindow);
return m_props.m_hWnd;
}
};
class QPropertyCtrl
: public TemplatePropertyCtrl <CPropertyCtrl>
{
public:
QPropertyCtrl(QWidget* parent)
: TemplatePropertyCtrl<CPropertyCtrl>(parent)
{
}
};
@@ -0,0 +1,123 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "Color.h"
#include "Serialization/IArchive.h"
#include <math.h>
#include "MathUtils.h"
// HSV
// h=0..360, s=0..1, v=0..1
inline void HSVtoRGB(float h,float s,float v,
float& r,float& g,float& b)
{
const float min=1e-5f;
int i;
float f,m,n,k;
if(s<min){
r=g=b=v;
}
else {
if(h>=360.0f)
h=0;
else
h=h/60.0f;
i=xround(floor(h));
f=h-i;
m=v*(1-s);
n=v*(1-s*f);
k=v*(1-s*(1-f));
switch(i){
case 0:
r=v; g=k; b=m;
break;
case 1:
r=n; g=v; b=m;
break;
case 2:
r=m; g=v; b=k;
break;
case 3:
r=m; g=n; b=v;
break;
case 4:
r=k; g=m; b=v;
break;
case 5:
r=v; g=m; b=n;
break;
default:
YASLI_ASSERT(0);
}
}
YASLI_ASSERT(r>=0 && r<=1);
YASLI_ASSERT(g>=0 && g<=1);
YASLI_ASSERT(b>=0 && b<=1);
}
void Color::setHSV(float h,float s,float v, unsigned char alpha)
{
float rf,gf,bf;
HSVtoRGB(h,s,v, rf,gf,bf);
r = xround(rf*255);
g = xround(gf*255);
b = xround(bf*255);
a = alpha;
}
void Color::toHSV(float& h,float& s,float& v)
{
float rf = r/255.f;
float gf = g/255.f;
float bf = b/255.f;
v = max(max(rf,gf),bf);
float temp=min(min(rf,gf),bf);
if(v==0)
s=0;
else
s=(v-temp)/v;
if(s==0)
h=0;
else {
float Cr=(v-rf)/(v-temp);
float Cg=(v-gf)/(v-temp);
float Cb=(v-bf)/(v-temp);
if(rf==v) {
h=Cb-Cg;
}
else if(gf==v) {
h=2+Cr-Cb;
}
else if(bf==v) {
h=4+Cg-Cr;
}
h=60*h;
if(h<0)h+=360;
}
}
void Color::Serialize(Serialization::IArchive& ar)
{
ar(r, "", "^R");
ar(g, "", "^G");
ar(b, "", "^B");
ar(a, "", "^A");
}
@@ -0,0 +1,66 @@
// Modifications copyright Amazon.com, Inc. or its affiliates.
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
#pragma once
namespace Serialization {
class IArchive;
}
struct Color
{
unsigned char b, g, r, a;
Color() : r(255), g(255), b(255), a(255) { }
Color(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a = 255) { r=_r; g=_g; b=_b; a=_a; }
explicit Color(unsigned long _argb) { argb() = _argb; }
void set(int rc,int gc,int bc,int ac = 255) { r=rc; g=gc; b=bc; a=ac; }
Color& setGDI(unsigned long color) {
b = (unsigned char)(color >> 16);
g = (unsigned char)(color >> 8);
r = (unsigned char)(color);
a = 255;
return *this;
}
void setHSV(float h,float s,float v, unsigned char alpha = 255);
void toHSV(float& h,float& s, float& v);
Color& operator*= (float f) { r=int(r*f); g=int(g*f); b=int(b*f); a=int(a*f); return *this; }
Color& operator+= (Color &p) { r+=p.r; g+=p.g; b+=p.b; a+=p.a; return *this; }
Color& operator-= (Color &p) { r-=p.r; g-=p.g; b-=p.b; a-=p.a; return *this; }
Color operator+ (Color &p) { return Color(r+p.r,g+p.g,b+p.b,a+p.a); }
Color operator- (Color &p) { return Color(r-p.r,g-p.g,b-p.b,a-p.a); }
Color operator* (float f) const { return Color(int(r*f), int(g*f), int(b*f), int(a*f)); }
Color operator* (int f) const { return Color(r*f,g*f,b*f,a*f); }
Color operator/ (int f) const { if(f!=0) f=(1<<16)/f; else f=1<<16; return Color((r*f)>>16,(g*f)>>16,(b*f)>>16,(a*f)>>16); }
bool operator==(const Color& rhs) const { return argb() == rhs.argb(); }
bool operator!=(const Color& rhs) const { return argb() != rhs.argb(); }
unsigned long argb() const { return *reinterpret_cast<const unsigned long*>(this); }
unsigned long& argb() { return *reinterpret_cast<unsigned long*>(this); }
unsigned long rgb() const { return r | g << 8 | b << 16; }
unsigned long rgba() const { return r | g << 8 | b << 16 | a << 24; }
unsigned char& operator[](int i) { return ((unsigned char*)this)[i];}
Color interpolate(const Color &v, float f) const
{
return Color(int(r+int(v.r-r)*f),
int(g+int(v.g-g)*f),
int(b+int(v.b-b)*f),
int(a+(v.a-a)*f));
}
void Serialize(Serialization::IArchive& ar);
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_COLOR_H
@@ -0,0 +1,58 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "ConstStringList.h"
#include <algorithm>
#include "Serialization/STL.h"
#include "Serialization/IArchive.h"
#include "Serialization/STLImpl.h"
ConstStringList globalConstStringList;
const char* ConstStringList::findOrAdd(const char* string)
{
// TODO: try sorted vector of const char*
Strings::iterator it = std::find(strings_.begin(), strings_.end(), string);
if (it == strings_.end()) {
strings_.push_back(string);
return strings_.back().c_str();
}
else {
return it->c_str();
}
}
ConstStringWrapper::ConstStringWrapper(ConstStringList* list, const char*& string)
: list_(list ? list : &globalConstStringList)
, string_(string)
{
YASLI_ASSERT(string_);
}
using Serialization::string;
bool Serialize(Serialization::IArchive& ar, ConstStringWrapper& val, const char* name, const char* label)
{
if (ar.IsOutput()) {
YASLI_ASSERT(val.string_);
string out = val.string_;
return ar(out, name, label);
}
else {
string in;
bool result = ar(in, name, label);
val.string_ = val.list_->findOrAdd(in.c_str());
return result;
}
}
@@ -0,0 +1,46 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
#pragma once
#include <list>
#include <string>
#include "EditorCommonAPI.h"
class ConstStringWrapper;
namespace Serialization { class IArchive; }
bool Serialize(Serialization::IArchive& ar, ConstStringWrapper &wrapper, const char* name, const char* label);
class ConstStringList{
public:
const char* findOrAdd(const char* string);
protected:
typedef std::list<std::string> Strings;
Strings strings_;
};
class ConstStringWrapper {
public:
ConstStringWrapper(ConstStringList* list, const char*& string);
protected:
ConstStringList* list_;
const char*& string_;
friend bool ::Serialize(Serialization::IArchive& ar, ConstStringWrapper &wrapper, const char* name, const char* label);
};
extern ConstStringList globalConstStringList;
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONSTSTRINGLIST_H
@@ -0,0 +1,76 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
#pragma once
#include <Serialization/IArchive.h>
namespace Serialization
{
class CContextList
{
public:
template<class T>
void Update(T* contextObject)
{
for (size_t i = 0; i < links_.size(); ++i)
{
if (links_[i]->type == TypeID::get<T>())
{
links_[i]->contextObject = (void*)contextObject;
return;
}
}
SContextLink* newLink = new SContextLink;
newLink->type = TypeID::get<T>();
newLink->outer = links_.empty() ? connectedList_ : links_.back();
newLink->contextObject = (void*)contextObject;
tail_.outer = newLink;
links_.push_back(newLink);
}
CContextList()
{
tail_.outer = 0;
tail_.contextObject = 0;
connectedList_ = 0;
}
explicit CContextList(SContextLink* connectedList)
{
tail_.outer = 0;
tail_.contextObject = 0;
connectedList_ = connectedList;
}
~CContextList()
{
for (size_t i = 0; i < links_.size(); ++i)
{
delete links_[i];
}
links_.clear();
}
SContextLink* Tail() { return &tail_; }
private:
SContextLink tail_;
std::vector<SContextLink*> links_;
SContextLink* connectedList_;
};
}
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_CONTEXTLIST_H
@@ -0,0 +1,156 @@
/**
* yasli - Serialization Library.
* Copyright (C) 2007-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
#pragma once
#include <AzCore/std/containers/map.h>
#include <AzCore/std/functional.h>
#include "Serialization/Assert.h"
template<class _Key, class _Product, class _KeyPred = std::less<_Key>>
class Factory {
public:
typedef AZStd::map<_Key, AZStd::function<_Product *()>, _KeyPred, AZ::StdLegacyAllocator> Creators;
typedef _Product* (*ProductConstructionFunction)(void);
Factory() {}
struct Creator
{
Creator()
{
if (s_creatorsHead)
{
m_next = s_creatorsHead;
}
s_creatorsHead = this;
}
Creator(Factory& factory, _Key key, ProductConstructionFunction construction_function_)
: Creator()
{
// capture key and construction_function_ by value so the lazy load won't try to access possibly deleted data
Register = [&, key, construction_function_]()
{
factory.add(key, construction_function_);
};
}
Creator(_Key key, ProductConstructionFunction construction_function_)
: Creator()
{
// capture key and construction_function_ by value so the lazy load won't try to access possibly deleted data
Register = [&, key, construction_function_]()
{
Factory::the().add(key, construction_function_);
};
}
AZStd::function<void()> Register;
Creator* m_next = nullptr;
};
void add(const _Key& key, AZStd::function<_Product *()> creator) {
YASLI_ASSERT(creators_.find(key) == creators_.end());
YASLI_ASSERT(creator);
creators_[key] = creator;
}
void remove(const _Key& key) {
auto& entry = creators_.find(key);
if (entry != creators_.end()) {
creators_.erase(entry);
}
}
_Product* create(const _Key& key) const
{
lazyRegisterCreators();
typename Creators::const_iterator it = creators_.find(key);
if (it != creators_.end()) {
return it->second();
}
else
return 0;
}
std::size_t size() const
{
lazyRegisterCreators();
return creators_.size();
}
_Product* createByIndex(int index) const
{
lazyRegisterCreators();
YASLI_ASSERT(index >= 0 && index < creators_.size());
typename Creators::const_iterator it = creators_.begin();
std::advance(it, index);
return it->second();
}
const Creators& creators() const
{
lazyRegisterCreators();
return creators_;
}
static Factory& the()
{
static Factory* genericFactory = nullptr;
static AZStd::aligned_storage_for_t<Factory> s_storage;
if (!genericFactory)
{
genericFactory = new(&s_storage) Factory();
}
return *genericFactory;
}
private:
void lazyRegisterCreators() const
{
if (s_creatorsHead)
{
Creator* creator = s_creatorsHead;
while (creator)
{
creator->Register();
creator = creator->m_next;
}
s_creatorsHead = nullptr;
}
}
protected:
Creators creators_;
static Creator* s_creatorsHead;
};
template <class _Key, class _Product, class _KeyPred>
typename Factory<_Key, _Product, _KeyPred>::Creator* Factory<_Key, _Product, _KeyPred>::s_creatorsHead = nullptr;
#define REGISTER_IN_FACTORY(factory, key, product, construction_function) \
static factory::Creator factory##product##Creator(key, construction_function);
#define REGISTER_IN_FACTORY_INSTANCE(factory, factoryType, key, product) \
static factoryType::Creator<product> factoryType##product##Creator(factory, key);
#define DECLARE_SEGMENT(fileName) int dataSegment##fileName;
#define FORCE_SEGMENT(fileName) \
extern int dataSegment##fileName; \
int* dataSegmentPtr##fileName = &dataSegment##fileName;
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_FACTORY_H
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
#pragma once
inline int xround(float v)
{
return int(v + 0.5f);
}
inline int min(int a, int b)
{
return a < b ? a : b;
}
inline int max(int a, int b)
{
return a > b ? a : b;
}
inline float min(float a, float b)
{
return a < b ? a : b;
}
inline float max(float a, float b)
{
return a > b ? a : b;
}
inline float clamp(float value, float min, float max)
{
return ::min(::max(min, value), max);
}
inline int clamp(int value, int min, int max)
{
return ::min(::max(min, value), max);
}
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_MATHUTILS_H
@@ -0,0 +1,466 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "PropertyDrawContext.h"
#include <memory>
#include "QPropertyTree.h"
#include "Serialization/Decorators/IconXPM.h"
#include "Unicode.h"
#include <QApplication>
#include <QStyleOption>
#include <QPainter>
#include <QBitmap>
// required to create context for the draw calls
#include <QPushButton>
#include <QCheckBox>
#include <QLineEdit>
#include <AzQtComponents/Components/StyleManager.h>
#ifndef _MSC_VER
# define _stricmp strcasecmp
#endif
// ---------------------------------------------------------------------------
QColor interpolateColor(const QColor& a, const QColor& b, float k);
IconXPMCache::~IconXPMCache()
{
flush();
}
void IconXPMCache::flush()
{
IconToBitmap::iterator it;
for (it = iconToImageMap_.begin(); it != iconToImageMap_.end(); ++it)
delete it->second.bitmap;
iconToImageMap_.clear();
}
struct RGBAImage
{
int width_;
int height_;
std::vector<Color> pixels_;
RGBAImage() : width_(0), height_(0) {}
};
bool IconXPMCache::parseXPM(RGBAImage* out, const Serialization::IconXPM& icon)
{
if (icon.lineCount < 3) {
return false;
}
// parse values
std::vector<Color> pixels;
int width = 0;
int height = 0;
int charsPerPixel = 0;
int colorCount = 0;
int hotSpotX = -1;
int hotSpotY = -1;
int scanResult = azsscanf(icon.source[0], "%d %d %d %d %d %d", &width, &height, &colorCount, &charsPerPixel, &hotSpotX, &hotSpotY);
if (scanResult != 4 && scanResult != 6)
return false;
if (charsPerPixel > 4)
return false;
if (icon.lineCount != 1 + colorCount + height) {
YASLI_ASSERT(0 && "Wrong line count");
return false;
}
// parse colors
std::vector<std::pair<int, Color> > colors;
colors.resize(colorCount);
for (int colorIndex = 0; colorIndex < colorCount; ++colorIndex) {
const char* p = icon.source[colorIndex + 1];
int code = 0;
for (int charIndex = 0; charIndex < charsPerPixel; ++charIndex) {
if (*p == '\0')
return false;
code = (code << 8) | *p;
++p;
}
colors[colorIndex].first = code;
while (*p == '\t' || *p == ' ')
++p;
if (*p == '\0')
return false;
if (*p != 'c' && *p != 'g')
return false;
++p;
while (*p == '\t' || *p == ' ')
++p;
if (*p == '\0')
return false;
if (*p == '#') {
++p;
if (strlen(p) == 6) {
int colorCode;
if (azsscanf(p, "%x", &colorCode) != 1)
return false;
Color color((colorCode & 0xff0000) >> 16,
(colorCode & 0xff00) >> 8,
(colorCode & 0xff),
255);
colors[colorIndex].second = color;
}
}
else {
if (_stricmp(p, "None") == 0)
colors[colorIndex].second = Color(0, 0, 0, 0);
else if (_stricmp(p, "Black") == 0)
colors[colorIndex].second = Color(0, 0, 0, 255);
else {
// unknown color
colors[colorIndex].second = Color(255, 0, 0, 255);
}
}
}
// parse pixels
pixels.resize(width * height);
int pi = 0;
for (int y = 0; y < height; ++y) {
const char* p = icon.source[1 + colorCount + y];
if (strlen(p) != width * charsPerPixel)
return false;
for (int x = 0; x < width; ++x) {
int code = 0;
for (int i = 0; i < charsPerPixel; ++i) {
code = (code << 8) | *p;
++p;
}
for (size_t i = 0; i < size_t(colorCount); ++i)
if (colors[i].first == code)
pixels[pi] = colors[i].second;
++pi;
}
}
out->pixels_.swap(pixels);
out->width_ = width;
out->height_ = height;
return true;
}
QImage* IconXPMCache::getImageForIcon(const Serialization::IconXPM& icon)
{
IconToBitmap::iterator it = iconToImageMap_.find(icon.source);
if (it != iconToImageMap_.end())
return it->second.bitmap;
RGBAImage image;
if (!parseXPM(&image, icon))
return 0;
BitmapCache& cache = iconToImageMap_[icon.source];
cache.pixels.swap(image.pixels_);
cache.bitmap = new QImage((unsigned char*)&cache.pixels[0], image.width_, image.height_, QImage::Format_ARGB32);
return cache.bitmap;
}
// ---------------------------------------------------------------------------
void drawRoundRectangle(QPainter& p, const QRect &_r, unsigned int color, int radius, [[maybe_unused]] int width)
{
QRect r = _r;
int dia = 2 * radius;
p.setPen(QColor(color));
p.drawRoundedRect(r, dia, dia);
}
void fillRoundRectangle(QPainter& p, const QBrush& brush, const QRect& _r, const QColor& border, int radius)
{
bool wasAntialisingSet = p.renderHints().testFlag(QPainter::Antialiasing);
p.setRenderHints(QPainter::Antialiasing, true);
p.setBrush(brush);
QPen pen(QBrush(border), 1.0, Qt::SolidLine);
p.setPen(pen);
QRectF adjustedRect = _r;
adjustedRect.adjust(0.5f, 0.5f, -0.5f, -0.5f);
p.drawRoundedRect(adjustedRect, radius, radius);
p.setRenderHints(QPainter::Antialiasing, wasAntialisingSet);
}
// ---------------------------------------------------------------------------
void PropertyDrawContext::drawIcon(const QRect& rect, const Serialization::IconXPM& icon) const
{
QImage* image = tree->_iconCache()->getImageForIcon(icon);
if (!image)
return;
int x = rect.left() + (rect.width() - image->width()) / 2;
int y = rect.top() + (rect.height() - image->height()) / 2;
painter->drawImage(x, y, *image);
}
void PropertyDrawContext::drawCheck(const QRect& rect, bool disabled, CheckState checked) const
{
QStyleOptionButton option;
if (!disabled)
option.state |= QStyle::State_Enabled;
else {
option.state |= QStyle::State_ReadOnly;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
if (checked == CHECK_SET)
option.state |= QStyle::State_On;
else if (checked == CHECK_IN_BETWEEN)
option.state |= QStyle::State_NoChange;
else
option.state |= QStyle::State_Off;
// create a widget so that the style sheet has context for its draw calls
QCheckBox forContext;
QSize checkboxSize = tree->style()->subElementRect(QStyle::SE_CheckBoxIndicator, &option, &forContext).size();
option.rect = QRect(rect.left(), rect.center().y() - checkboxSize.height() / 2, checkboxSize.width(), checkboxSize.height());
tree->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &forContext);
if (disabled) {
// With Fusion theme difference between disabled and enabled checkbox is very subtle, let's amplify it
QColor readOnlyOverlay = tree->backgroundColor();
readOnlyOverlay.setAlpha(128);
painter->fillRect(option.rect, QBrush(readOnlyOverlay));
}
}
void PropertyDrawContext::drawButton(const QRect& rect, const wchar_t* text, int buttonFlags, const QFont* font, const Color* colorOverride) const
{
QPushButton button;
button.ensurePolished();
QStyleOptionButton option;
option.initFrom(&button);
if (buttonFlags & BUTTON_DISABLED) {
option.state |= QStyle::State_ReadOnly;
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
else
option.state |= QStyle::State_Enabled;
if (buttonFlags & BUTTON_PRESSED) {
option.state |= QStyle::State_On;
option.state |= QStyle::State_Sunken;
}
else
option.state |= QStyle::State_Raised;
if (buttonFlags & BUTTON_FOCUSED)
option.state |= QStyle::State_HasFocus;
option.rect = rect.adjusted(0, 0, -1, -1);
QWidget* pseudoDrawWidget = &button;
if (colorOverride) {
QPalette& palette = option.palette;
palette.setCurrentColorGroup(QPalette::Normal);
QColor tintTarget(colorOverride->r, colorOverride->g, colorOverride->b, colorOverride->a);
QPalette::ColorRole groups[] = { QPalette::Button, QPalette::Light, QPalette::Dark, QPalette::Midlight, QPalette::Mid, QPalette::Shadow };
for (int i = 0; i < sizeof(groups) / sizeof(groups[0]); ++i)
palette.setColor(groups[i], interpolateColor(palette.color(groups[i]), tintTarget, 0.11f));
tree->style()->drawControl(QStyle::CE_PushButtonBevel, &option, painter, pseudoDrawWidget);
}
else
{
// Previously, a temporary QPushButton widget was used as the drawing aid
// for this control. However, our stylesheets didn't seem to affect the
// QPushButton as intended, which left some of them with incorrect background
// colors. It seemed to work to let the tree be the drawing aid, but we should
// probably revisit this in the future.
tree->style()->drawControl(QStyle::CE_PushButtonBevel, &option, painter, pseudoDrawWidget);
}
QRect textRect;
if ((buttonFlags & BUTTON_DISABLED) == 0 && buttonFlags & BUTTON_POPUP_ARROW)
{
QStyleOption arrowOption;
arrowOption.rect = QRect(rect.right() - 11, rect.top(), 8, rect.height());
arrowOption.state |= QStyle::State_Enabled;
// part of the above context change
tree->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOption, painter, tree);
textRect = rect.adjusted(0, 0, -8, 0);
}
else
{
textRect = rect;
}
if (buttonFlags & BUTTON_PRESSED)
{
textRect = textRect.adjusted(1, 0, 1, 0);
}
if ((buttonFlags & BUTTON_CENTER) == 0)
{
textRect.adjust(4, 0, -5, 0);
}
QColor textColor;
if (colorOverride && !(buttonFlags & BUTTON_DISABLED))
{
textColor = interpolateColor(tree->palette().color(QPalette::Normal, QPalette::ButtonText),
QColor(colorOverride->r, colorOverride->g, colorOverride->b, colorOverride->a), 0.4f);
}
else
{
textColor = tree->palette().color((buttonFlags & BUTTON_DISABLED) ? QPalette::Disabled : QPalette::Normal, QPalette::ButtonText);
}
tree->_drawRowValue(*painter, text, font, textRect, textColor, false, (buttonFlags & BUTTON_CENTER) != 0);
}
void PropertyDrawContext::drawButtonWithIcon(const QIcon& icon, const QRect& rect, const wchar_t* text, bool selected, bool pressed, bool focused, bool enabled, bool showButtonFrame, const QFont* font) const
{
QStyleOptionButton option;
if (enabled)
option.state |= QStyle::State_Enabled;
else
option.state |= QStyle::State_ReadOnly;
if (pressed) {
option.state |= QStyle::State_On;
option.state |= QStyle::State_Sunken;
}
else
option.state |= QStyle::State_Raised;
if (focused)
option.state |= QStyle::State_HasFocus;
option.rect = rect.adjusted(0, 0, -1, -1);
// See the comment in the drawButton method above for why we don't use the
// QPushButton as the drawing aid for this control
if (showButtonFrame)
tree->style()->drawControl(QStyle::CE_PushButton, &option, painter, tree);
int iconSize = 16;
QRect iconRect(rect.topLeft(), QPoint(rect.left() + iconSize, rect.bottom()));
QRect textRect;
if (enabled)
textRect = rect.adjusted(iconSize, 0, -8, 0);
else
textRect = rect.adjusted(iconSize, 0, 0, 0);
if (pressed)
{
textRect.adjust(5, 0, 1, 0);
iconRect.adjust(4, 0, 4, 0);
}
else
{
textRect.adjust(4, 0, 0, 0);
iconRect.adjust(3, 0, 3, 0);
}
icon.paint(painter, iconRect);
QColor textColor = tree->palette().color(enabled ? QPalette::Active : QPalette::Disabled, selected && !showButtonFrame ? QPalette::HighlightedText : QPalette::ButtonText);
tree->_drawRowValue(*painter, text, font, textRect, textColor, false, false);
}
void PropertyDrawContext::drawValueText(bool highlighted, const wchar_t* text) const
{
QColor textColor = highlighted ? tree->palette().highlight().color() : tree->palette().buttonText().color();
QRect textRect(widgetRect.left() + 3, widgetRect.top() + 2, widgetRect.width() - 6, widgetRect.height() - 4);
tree->_drawRowValue(*painter, text, &tree->font(), textRect, textColor, false, false);
}
void PropertyDrawContext::drawEntry(const wchar_t* text, bool pathEllipsis, bool grayBackground, int trailingOffset) const
{
QRect rt = widgetRect;
rt.adjust(0, 0, -trailingOffset, 0);
// the drawing context requires context so that the style sheet can be used:
QFrame frameForContext;
QLineEdit forContext;
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
QStyleOptionFrameV2 option;
option.features = QStyleOptionFrameV2::None;
#else
QStyleOptionFrame option;
option.features = QStyleOptionFrame::None;
#endif
option.state = QStyle::State_Sunken;
option.lineWidth = tree->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, &frameForContext);
option.midLineWidth = 0;
if (!grayBackground)
option.state |= QStyle::State_Enabled;
else {
option.palette.setCurrentColorGroup(QPalette::Disabled);
}
if (captured)
option.state |= QStyle::State_HasFocus;
option.rect = rt; // option.rect is the rectangle to be drawn on.
QRect textRect = tree->style()->subElementRect(QStyle::SE_LineEditContents, &option, &forContext);
if (!textRect.isValid())
{
textRect = rt;
textRect.adjust(3, 1, -3, -2);
}
else {
textRect.adjust(2, 1, -2, -1);
}
// make sure the context control is polished (ie, ready for rendering) since we need to use its color palette:
forContext.ensurePolished();
// some styles rely on default pens
painter->setPen(QPen(forContext.palette().color(QPalette::Text)));
painter->setBrush(QBrush(forContext.palette().color(QPalette::Base)));
tree->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, painter, &forContext);
tree->_drawRowValue(*painter, text, &tree->font(), textRect, forContext.palette().color(QPalette::Text), pathEllipsis, false);
// end amazno changes
}
QFont* propertyTreeDefaultFont()
{
static QFont font;
return &font;
}
QFont* propertyTreeDefaultBoldFont()
{
static QFont font;
font.setBold(true);
return &font;
}
@@ -0,0 +1,98 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
#pragma once
#include <map>
#include <vector>
#include <QRect>
#include "Color.h"
#include "EditorCommonAPI.h"
class QPainter;
class QImage;
class QBrush;
class QRect;
class QIcon;
class QColor;
class QFont;
struct RGBAImage;
namespace Serialization { struct IconXPM; }
struct Color;
struct IconXPMCache
{
void initialize();
void finalize();
void flush();
~IconXPMCache();
QImage* getImageForIcon(const Serialization::IconXPM& icon);
private:
struct BitmapCache {
std::vector<Color> pixels;
QImage* bitmap;
};
static bool parseXPM(RGBAImage* out, const Serialization::IconXPM& xpm);
typedef std::map<const char* const*, BitmapCache> IconToBitmap;
IconToBitmap iconToImageMap_;
};
void fillRoundRectangle(QPainter& p, const QBrush& brush, const QRect& r, const QColor& borderColor, int radius);
void drawRoundRectangle(QPainter& p, const QRect &_r, unsigned int color, int radius, int width);
enum CheckState {
CHECK_SET,
CHECK_NOT_SET,
CHECK_IN_BETWEEN
};
enum {
BUTTON_POPUP_ARROW = 1 << 0,
BUTTON_DISABLED = 1 << 1,
BUTTON_FOCUSED = 1 << 2,
BUTTON_PRESSED = 1 << 3,
BUTTON_CENTER = 1 << 4
};
class QPropertyTree;
struct EDITOR_COMMON_API PropertyDrawContext {
const QPropertyTree* tree;
QPainter* painter;
QRect widgetRect;
QRect lineRect;
bool captured;
bool m_pressed;
void drawIcon(const QRect& rect, const Serialization::IconXPM& icon) const;
void drawCheck(const QRect& rect, bool disabled, CheckState checked) const;
void drawButton(const QRect& rect, const wchar_t* text, int buttonFlags, const QFont* font, const Color* optionalColorOverride = 0) const;
void drawButtonWithIcon(const QIcon& icon, const QRect& rect, const wchar_t* text, bool selected, bool pressed, bool focused, bool enabled, bool showButtonFrame, const QFont* font) const;
void drawValueText(bool highlighted, const wchar_t* text) const;
void drawEntry(const wchar_t* text, bool pathEllipsis, bool grayBackground, int trailingOffset) const;
PropertyDrawContext()
: tree(0)
, painter(0)
, captured(false)
, m_pressed(false)
{
}
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYDRAWCONTEXT_H
@@ -0,0 +1,377 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "Serialization.h"
#include "Serialization/Enum.h"
#include "Serialization/Callback.h"
#include "PropertyTreeModel.h"
#include "PropertyIArchive.h"
#include "PropertyRowBool.h"
#include "PropertyRowString.h"
#include "PropertyRowNumber.h"
#include "PropertyRowPointer.h"
#include "PropertyRowObject.h"
#include "Unicode.h"
using Serialization::TypeID;
PropertyIArchive::PropertyIArchive(PropertyTreeModel* model, PropertyRow* root)
: IArchive(INPUT | EDIT)
, model_(model)
, currentNode_(0)
, lastNode_(0)
, root_(root)
{
stack_.push_back(Level());
if (!root_)
root_ = model_->root();
else
currentNode_ = root;
}
bool PropertyIArchive::operator()(Serialization::IString& value, const char* name, const char* label)
{
if(openRow(name, label, "string")){
if(PropertyRowString* row = static_cast<PropertyRowString*>(currentNode_))
value.set(fromWideChar(row->value().c_str()).c_str());
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(Serialization::IWString& value, const char* name, const char* label)
{
if(openRow(name, label, "string")){
if(PropertyRowString* row = static_cast<PropertyRowString*>(currentNode_)) {
value.set(row->value().c_str());
}
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(bool& value, const char* name, const char* label)
{
if(openRow(name, label, "bool")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(char& value, const char* name, const char* label)
{
if(openRow(name, label, "char")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
// Signed types
bool PropertyIArchive::operator()(int8& value, const char* name, const char* label)
{
if(openRow(name, label, "int8")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(int16& value, const char* name, const char* label)
{
if(openRow(name, label, "int16")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(int32& value, const char* name, const char* label)
{
if(openRow(name, label, "int32")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(int64& value, const char* name, const char* label)
{
if(openRow(name, label, "int64")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
// Unsigned types
bool PropertyIArchive::operator()(uint8& value, const char* name, const char* label)
{
if(openRow(name, label, "uint8")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(uint16& value, const char* name, const char* label)
{
if(openRow(name, label, "uint16")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(uint32& value, const char* name, const char* label)
{
if(openRow(name, label, "uint32")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(uint64& value, const char* name, const char* label)
{
if(openRow(name, label, "uint64")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(float& value, const char* name, const char* label)
{
if(openRow(name, label, "float")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(double& value, const char* name, const char* label)
{
if(openRow(name, label, "double")){
currentNode_->assignToPrimitive(&value, sizeof(value));
closeRow(name);
return true;
}
else
return false;
}
bool PropertyIArchive::operator()(Serialization::IContainer& ser, const char* name, const char* label)
{
const char* typeName = ser.containerType().name();
if(!openRow(name, label, typeName))
return false;
size_t size = 0;
if(currentNode_->multiValue())
size = ser.size();
else{
size = currentNode_->count();
size = ser.resize(size);
}
stack_.push_back(Level());
size_t index = 0;
if(ser.size() > 0)
while(index < size)
{
ser(*this, "", "<");
ser.next();
++index;
}
stack_.pop_back();
closeRow(name);
return true;
}
bool PropertyIArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
{
PropertyRow* nonLeafNode = 0;
if(openRow(name, label, ser.type().name())){
if (currentNode_->isLeaf()) {
if(!currentNode_->isRoot()){
currentNode_->assignTo(ser);
closeRow(name);
return true;
}
}
else
nonLeafNode = currentNode_;
}
else
return false;
stack_.push_back(Level());
ser(*this);
stack_.pop_back();
if (nonLeafNode)
nonLeafNode->closeNonLeaf(ser, *this);
closeRow(name);
return true;
}
bool PropertyIArchive::operator()(Serialization::IPointer& ser, const char* name, const char* label)
{
const char* baseName = ser.baseType().name();
if(openRow(name, label, baseName)){
if (!currentNode_->isPointer()) {
closeRow(name);
return false;
}
YASLI_ASSERT(currentNode_);
PropertyRowPointer* row = static_cast<PropertyRowPointer*>(currentNode_);
if(!row){
closeRow(name);
return false;
}
row->assignTo(ser);
}
else
return false;
stack_.push_back(Level());
if(ser.get() != 0)
ser.serializer()( *this );
stack_.pop_back();
closeRow(name);
return true;
}
bool PropertyIArchive::operator()(Serialization::ICallback& callback, const char* name, const char* label)
{
return callback.SerializeValue(*this, name, label);
}
bool PropertyIArchive::operator()(Serialization::Object& obj, const char* name, const char* label)
{
if(openRow(name, label, obj.type().name())){
bool result = false;
if (currentNode_->isObject()) {
PropertyRowObject* rowObj = static_cast<PropertyRowObject*>(currentNode_);
result = rowObj->assignTo(&obj);
}
closeRow(name);
return result;
}
else
return false;
}
bool PropertyIArchive::OpenBlock(const char* name, const char* label)
{
if(openRow(name, label, "block")){
stack_.push_back(Level());
return true;
}
else
return false;
}
void PropertyIArchive::CloseBlock()
{
closeRow("block");
stack_.pop_back();
}
bool PropertyIArchive::openRow(const char* name, [[maybe_unused]] const char* label, const char* typeName)
{
if(!name)
return false;
if(!currentNode_){
lastNode_ = currentNode_ = model_->root();
YASLI_ASSERT(currentNode_);
if (currentNode_ && strcmp(currentNode_->typeName(), typeName) != 0)
return false;
return true;
}
YASLI_ESCAPE(currentNode_, return false);
if(currentNode_->empty())
return false;
Level& level = stack_.back();
PropertyRow* node = 0;
if(currentNode_->isContainer()){
if (level.rowIndex < int(currentNode_->children_.size()))
node = currentNode_->children_[level.rowIndex];
++level.rowIndex;
}
else {
node = currentNode_->findFromIndex(&level.rowIndex, name, typeName, level.rowIndex);
++level.rowIndex;
}
if(node){
lastNode_ = node;
if(node->isContainer() || !node->multiValue()){
currentNode_ = node;
if (currentNode_ && strcmp(currentNode_->typeName(), typeName) != 0)
return false;
return true;
}
}
return false;
}
void PropertyIArchive::closeRow([[maybe_unused]] const char* name)
{
YASLI_ESCAPE(currentNode_, return);
currentNode_ = currentNode_->parent();
}
@@ -0,0 +1,80 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
#pragma once
#include "Serialization/IArchive.h"
namespace Serialization{
class CEnumDescription;
class Object;
}
class PropertyRow;
class PropertyTreeModel;
class PropertyIArchive : public Serialization::IArchive{
public:
PropertyIArchive(PropertyTreeModel* model, PropertyRow* root);
protected:
bool operator()(Serialization::IString& value, const char* name, const char* label);
bool operator()(Serialization::IWString& value, const char* name, const char* label);
bool operator()(bool& value, const char* name, const char* label);
bool operator()(char& value, const char* name, const char* label);
// Signed types
bool operator()(int8& value, const char* name, const char* label);
bool operator()(int16& value, const char* name, const char* label);
bool operator()(int32& value, const char* name, const char* label);
bool operator()(int64& value, const char* name, const char* label);
// Unsigned types
bool operator()(uint8& value, const char* name, const char* label);
bool operator()(uint16& value, const char* name, const char* label);
bool operator()(uint32& value, const char* name, const char* label);
bool operator()(uint64& value, const char* name, const char* label);
bool operator()(float& value, const char* name, const char* label);
bool operator()(double& value, const char* name, const char* label);
bool operator()(const Serialization::SStruct& ser, const char* name, const char* label);
bool operator()(Serialization::IPointer& ser, const char* name, const char* label);
bool operator()(Serialization::IContainer& ser, const char* name, const char* label);
bool operator()(Serialization::Object& obj, const char* name, const char* label);
bool operator()(Serialization::ICallback& callback, const char* name, const char* label);
using Serialization::IArchive::operator();
bool OpenBlock(const char* name, const char* label);
void CloseBlock();
protected:
bool needDefaultArchive([[maybe_unused]] const char* baseName) const { return false; }
private:
bool openRow(const char* name, const char* label, const char* typeName);
void closeRow(const char* name);
struct Level {
int rowIndex;
Level() : rowIndex(0) {}
};
vector<Level> stack_;
PropertyTreeModel* model_;
PropertyRow* currentNode_;
PropertyRow* lastNode_;
PropertyRow* root_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYIARCHIVE_H
@@ -0,0 +1,494 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include <math.h>
#include <memory>
#include "PropertyTreeModel.h"
#include "QPropertyTree.h"
#include "PropertyRowContainer.h"
#include "PropertyRowBool.h"
#include "PropertyRowString.h"
#include "PropertyRowNumber.h"
#include "PropertyRowPointer.h"
#include "PropertyRowObject.h"
#include "ConstStringList.h"
#include "Unicode.h"
#include "Serialization.h"
#include "PropertyOArchive.h"
#include "Serialization/Callback.h"
using Serialization::TypeID;
PropertyOArchive::PropertyOArchive(PropertyTreeModel* model, PropertyRow* root, ValidatorBlock* validator)
: IArchive(OUTPUT | EDIT | VALIDATION | DOCUMENTATION)
, model_(model)
, currentNode_(root)
, lastNode_(0)
, updateMode_(false)
, defaultValueCreationMode_(false)
, rootNode_(root)
, outlineMode_(false)
, validator_(validator)
{
stack_.push_back(Level());
YASLI_ASSERT(model != 0);
if(!rootNode_->empty()){
updateMode_ = true;
stack_.back().oldRows.swap(rootNode_->children_);
}
}
PropertyOArchive::PropertyOArchive(PropertyTreeModel* model, bool forDefaultType)
: IArchive(OUTPUT | EDIT | VALIDATION | DOCUMENTATION)
, model_(model)
, currentNode_(0)
, lastNode_(0)
, updateMode_(false)
, defaultValueCreationMode_(forDefaultType)
, rootNode_(0)
, outlineMode_(false)
, validator_(0)
{
rootNode_ = new PropertyRow();
rootNode_->setName("root");
currentNode_ = rootNode_.get();
stack_.push_back(Level());
}
PropertyOArchive::~PropertyOArchive()
{
}
PropertyRow* PropertyOArchive::defaultValueRootNode()
{
if (!rootNode_)
return 0;
return rootNode_->childByIndex(0);
}
void PropertyOArchive::enterNode(PropertyRow* row)
{
currentNode_ = row;
stack_.push_back(Level());
Level& level = stack_.back();
level.oldRows.swap(row->children_);
row->children_.reserve(level.oldRows.size());
}
void PropertyOArchive::closeStruct([[maybe_unused]] const char* name)
{
stack_.pop_back();
if(currentNode_){
lastNode_ = currentNode_;
currentNode_ = currentNode_->parent();
}
}
static PropertyRow* findRow(int* index, PropertyRows& rows, const char* name, const char* typeName, int startIndex)
{
int count = int(rows.size());
for(int i = startIndex; i < count; ++i){
PropertyRow* row = rows[i];
if (!row)
continue;
if(((row->name() == name) || strcmp(row->name(), name) == 0) &&
(row->typeName() == typeName || strcmp(row->typeName(), typeName) == 0)) {
*index = (int)i;
return row;
}
}
for(int i = 0; i < startIndex; ++i){
PropertyRow* row = rows[i];
if (!row)
continue;
if(((row->name() == name) || strcmp(row->name(), name) == 0) &&
(row->typeName() == typeName || strcmp(row->typeName(), typeName) == 0)) {
*index = (int)i;
return row;
}
}
return 0;
}
template<class RowType, class ValueType>
RowType* PropertyOArchive::updateRow(const char* name, const char* label, const char* typeName, const ValueType& value)
{
SharedPtr<RowType> newRow;
if(currentNode_ == 0){
if (rootNode_)
newRow = static_cast<RowType*>(rootNode_.get());
else
newRow.reset(new RowType());
newRow->setNames(name, label, typeName);
if(updateMode_){
model_->setRoot(newRow);
return newRow;
}
else{
if(defaultValueCreationMode_)
rootNode_ = newRow;
else
model_->setRoot(newRow);
newRow->setValueAndContext(value, *this);
return newRow;
}
}
else{
Level& level = stack_.back();
int rowIndex;
PropertyRow* oldRow = findRow(&rowIndex, level.oldRows, name, typeName, level.rowIndex);
const char* oldLabel = 0;
if(oldRow){
oldRow->setMultiValue(false);
newRow = static_cast<RowType*>(oldRow);
level.oldRows[rowIndex] = 0;
level.rowIndex = rowIndex + 1;
oldLabel = oldRow->label();
newRow->setNames(name, label, typeName);
}
else{
PropertyRowFactory& factory = PropertyRowFactory::the();
newRow = static_cast<RowType*>(factory.create(typeName));
if(!newRow)
newRow.reset(new RowType());
newRow->setNames(name, label, typeName);
if(model_->expandLevels() != 0 && (model_->expandLevels() == -1 || model_->expandLevels() >= currentNode_->level()))
newRow->_setExpanded(true);
}
currentNode_->add(newRow);
if (!oldRow || oldLabel != label) {
// for new rows we should mark all parents with labelChanged_
newRow->setLabelChanged();
newRow->setLabelChangedToChildren();
}
newRow->setValueAndContext(value, *this);
return newRow;
}
}
template<class RowType, class ValueType>
PropertyRow* PropertyOArchive::updateRowPrimitive(const char* name, const char* label, const char* typeName, const ValueType& value, const void* handle, const Serialization::TypeID& typeId)
{
SharedPtr<RowType> newRow;
if(currentNode_ == 0)
return 0;
int rowIndex;
Level& level = stack_.back();
PropertyRow* oldRow = findRow(&rowIndex, level.oldRows, name, typeName, level.rowIndex);
const char* oldLabel = 0;
if(oldRow){
oldRow->setMultiValue(false);
newRow.reset(static_cast<RowType*>(oldRow));
level.oldRows[rowIndex] = 0;
level.rowIndex = rowIndex + 1;
oldLabel = oldRow->label();
oldRow->setNames(name, label, typeName);
}
else{
newRow = new RowType();
newRow->setNames(name, label, typeName);
if(model_->expandLevels() != 0){
if(model_->expandLevels() == -1 || model_->expandLevels() >= currentNode_->level())
newRow->_setExpanded(true);
}
}
currentNode_->add(newRow);
if (!oldRow || oldLabel != label)
{
// for new rows we should mark all parents with labelChanged_
newRow->setLabelChanged();
}
newRow->setValue(value, handle, typeId);
return newRow;
}
bool PropertyOArchive::operator()(const Serialization::SStruct& ser, const char* name, const char* label)
{
const char* typeName = ser.type().name();
size_t size = ser.size();
lastNode_ = currentNode_;
bool hideChildren = outlineMode_ && currentNode_ && currentNode_->isContainer();
PropertyRow* row = updateRow<PropertyRow>(name, label, typeName, ser);
row->setHideChildren(hideChildren);
PropertyRow* nonLeaf = 0;
if(!row->isLeaf() || currentNode_ == 0){
enterNode(row);
if(currentNode_->isLeaf())
return false;
else
nonLeaf = currentNode_;
}
else{
lastNode_ = row;
return true;
}
if (ser)
ser(*this);
if (nonLeaf)
nonLeaf->closeNonLeaf(ser, *this);
closeStruct(name);
return true;
}
bool PropertyOArchive::operator()(Serialization::IString& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowString>(name, label, "string", value.get(), value.handle(), value.type());
return true;
}
bool PropertyOArchive::operator()(Serialization::IWString& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowString>(name, label, "string", value.get(), value.handle(), value.type());
return true;
}
bool PropertyOArchive::operator()(bool& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowBool>(name, label, "bool", value, &value, Serialization::TypeID::get<bool>());
return true;
}
bool PropertyOArchive::operator()(char& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<char> >(name, label, "char", value, &value, Serialization::TypeID::get<char>());
return true;
}
// ---
bool PropertyOArchive::operator()(int8& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<int8> >(name, label, "int8", value, &value, Serialization::TypeID::get<int8>());
return true;
}
bool PropertyOArchive::operator()(int16& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<int16> >(name, label, "int16", value, &value, Serialization::TypeID::get<int16>());
return true;
}
bool PropertyOArchive::operator()(int32& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<int32> >(name, label, "int32", value, &value, Serialization::TypeID::get<int32>());
return true;
}
bool PropertyOArchive::operator()(int64& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<int64> >(name, label, "int64", value, &value, Serialization::TypeID::get<int64>());
return true;
}
// ---
bool PropertyOArchive::operator()(uint8& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint8> >(name, label, "uint8", value, &value, Serialization::TypeID::get<uint8>());
return true;
}
bool PropertyOArchive::operator()(uint16& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint16> >(name, label, "uint16", value, &value, Serialization::TypeID::get<uint16>());
return true;
}
bool PropertyOArchive::operator()(uint32& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint32> >(name, label, "uint32", value, &value, Serialization::TypeID::get<uint32>());
return true;
}
bool PropertyOArchive::operator()(uint64& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<uint64> >(name, label, "uint64", value, &value, Serialization::TypeID::get<uint64>());
return true;
}
// ---
bool PropertyOArchive::operator()(float& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<float> >(name, label, "float", value, &value, Serialization::TypeID::get<float>());
return true;
}
bool PropertyOArchive::operator()(double& value, const char* name, const char* label)
{
lastNode_ = updateRowPrimitive<PropertyRowNumber<double> >(name, label, "double", value, &value, Serialization::TypeID::get<double>());
return true;
}
bool PropertyOArchive::operator()(Serialization::IContainer& ser, const char *name, const char *label)
{
const char* elementTypeName = ser.elementType().name();
bool fixedSizeContainer = ser.isFixedSize();
lastNode_ = currentNode_;
enterNode(updateRow<PropertyRowContainer>(name, label, ser.containerType().name(), ser));
if (!model_->defaultTypeRegistered(elementTypeName)) {
PropertyOArchive ar(model_, true);
ar.SetOutlineMode(outlineMode_);
ar.SetFilter(GetFilter());
ar.SetInnerContext(GetInnerContext());
model_->addDefaultType(0, elementTypeName); // add empty default to prevent recursion
ser.serializeNewElement(ar, "", (label&&*label=='!')?"!<":"<");
if (ar.defaultValueRootNode() != 0)
model_->addDefaultType(ar.defaultValueRootNode(), elementTypeName);
}
if ( ser.size() > 0 )
while( true ) {
ser(*this, "", (label&&*label=='!')?"!<":"<");
if ( !ser.next() )
break;
}
currentNode_->labelChanged();
closeStruct(name);
return true;
}
bool PropertyOArchive::operator()(Serialization::IPointer& ptr, const char *name, const char *label)
{
lastNode_ = currentNode_;
bool hideChildren = outlineMode_ && currentNode_ && currentNode_->isContainer();
PropertyRow* row = updateRow<PropertyRowPointer>(name, label, ptr.baseType().name(), ptr);
row->setHideChildren(hideChildren);
enterNode(row);
{
TypeID baseType = ptr.baseType();
Serialization::IClassFactory* factory = ptr.factory();
size_t count = factory->size();
const char* nullLabel = factory->nullLabel();
if (!(nullLabel && nullLabel[0] == '\0'))
{
PropertyDefaultDerivedTypeValue nullValue;
nullValue.factory = factory;
nullValue.factoryIndex = -1;
nullValue.label = nullLabel ? nullLabel : "[ null ]";
model_->addDefaultType(baseType, nullValue);
}
for(size_t i = 0; i < count; ++i) {
const Serialization::TypeDescription *desc = factory->descriptionByIndex((int)i);
if (!model_->defaultTypeRegistered(baseType, desc->name())){
PropertyOArchive ar(model_, true);
ar.SetOutlineMode(outlineMode_);
ar.SetInnerContext(GetInnerContext());
ar.SetFilter(GetFilter());
PropertyDefaultDerivedTypeValue defaultValue;
defaultValue.registeredName = desc->name();
defaultValue.factory = factory;
defaultValue.factoryIndex = int(i);
defaultValue.label = desc->label();
model_->addDefaultType(baseType, defaultValue);
factory->serializeNewByIndex(ar, (int)i, "name", "label");
if (ar.defaultValueRootNode() != 0) {
ar.defaultValueRootNode()->setTypeName(desc->name());
defaultValue.root = ar.defaultValueRootNode();
model_->addDefaultType(baseType, defaultValue);
}
}
}
}
if(Serialization::SStruct ser = ptr.serializer())
ser(*this);
closeStruct(name);
return true;
}
bool PropertyOArchive::operator()(Serialization::ICallback& callback, const char* name, const char* label)
{
if (!callback.SerializeValue(*this, name, label))
return false;
lastNode_->setCallback(callback.Clone());
return true;
}
bool PropertyOArchive::operator()(Serialization::Object& obj, const char *name, const char *label)
{
const char* typeName = obj.type().name();
PropertyRowObject* row = 0;
if (typeName_.empty())
row = updateRow<PropertyRowObject>(name, label, obj.type().name(), obj);
else
row = updateRow<PropertyRowObject>(name, label, obj.type().name(), obj);
lastNode_ = row;
return true;
}
bool PropertyOArchive::OpenBlock(const char* name, const char* label)
{
PropertyRow* row = updateRow<PropertyRow>(name, label, "block", Serialization::SStruct());
lastNode_ = currentNode_;
enterNode(row);
return true;
}
void PropertyOArchive::ValidatorMessage(bool error, const void* handle, const Serialization::TypeID& type, const char* message)
{
if (validator_)
{
ValidatorEntry entry(error ? VALIDATOR_ENTRY_ERROR : VALIDATOR_ENTRY_WARNING,
handle,
type,
message);
validator_->AddEntry(entry);
}
}
void PropertyOArchive::DocumentLastField(const char* message)
{
if (lastNode_ && (!currentNode_ || lastNode_->parent() == currentNode_))
lastNode_->setTooltip(message ? message : "");
else if (currentNode_)
currentNode_->setTooltip(message ? message : "");
}
void PropertyOArchive::CloseBlock()
{
closeStruct("block");
}
void PropertyOArchive::SetOutlineMode(bool outlineMode)
{
outlineMode_ = outlineMode;
}
// vim:ts=4 sw=4:
@@ -0,0 +1,112 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
#pragma once
#include "Serialization/IArchive.h"
#include "Serialization/Pointers.h"
namespace Serialization
{
class CEnumDescription;
class Object;
struct ICallback;
}
class PropertyRow;
class PropertyTreeModel;
class ValidatorBlock;
using Serialization::SharedPtr;
class PropertyOArchive : public Serialization::IArchive{
public:
PropertyOArchive(PropertyTreeModel* model, PropertyRow* root, ValidatorBlock* validator);
~PropertyOArchive();
void SetOutlineMode(bool outlineMode);
inline const SharedPtr<PropertyRow>& currentNode() const {
return currentNode_;
}
protected:
bool operator()(Serialization::IString& value, const char* name, const char* label);
bool operator()(Serialization::IWString& value, const char* name, const char* label);
bool operator()(bool& value, const char* name, const char* label);
bool operator()(char& value, const char* name, const char* label);
bool operator()(int8& value, const char* name, const char* label);
bool operator()(int16& value, const char* name, const char* label);
bool operator()(int32& value, const char* name, const char* label);
bool operator()(int64& value, const char* name, const char* label);
bool operator()(uint8& value, const char* name, const char* label);
bool operator()(uint16& value, const char* name, const char* label);
bool operator()(uint32& value, const char* name, const char* label);
bool operator()(uint64& value, const char* name, const char* label);
bool operator()(float& value, const char* name, const char* label);
bool operator()(double& value, const char* name, const char* label);
bool operator()(const Serialization::SStruct& ser, const char* name, const char* label);
bool operator()(Serialization::IPointer& ptr, const char *name, const char *label);
bool operator()(Serialization::IContainer& ser, const char *name, const char *label);
bool operator()(Serialization::Object& obj, const char *name, const char *label);
bool operator()(Serialization::ICallback& ser, const char *name, const char *label);
using Serialization::IArchive::operator();
bool OpenBlock(const char* name, const char* label);
void CloseBlock();
void ValidatorMessage(bool error, const void* handle, const Serialization::TypeID& type, const char* message);
void DocumentLastField(const char* docString);
protected:
PropertyOArchive(PropertyTreeModel* model, bool forDefaultType);
private:
struct Level {
std::vector<SharedPtr<PropertyRow> > oldRows;
int rowIndex;
Level() : rowIndex(0) {}
};
std::vector<Level> stack_;
template<class RowType, class ValueType>
PropertyRow* updateRowPrimitive(const char* name, const char* label, const char* typeName, const ValueType& value, const void* handle, const Serialization::TypeID& typeId);
template<class RowType, class ValueType>
RowType* updateRow(const char* name, const char* label, const char* typeName, const ValueType& value);
void enterNode(PropertyRow* row); // sets currentNode
void closeStruct(const char* name);
PropertyRow* defaultValueRootNode();
bool updateMode_;
bool defaultValueCreationMode_;
PropertyTreeModel* model_;
ValidatorBlock* validator_;
SharedPtr<PropertyRow> currentNode_;
SharedPtr<PropertyRow> lastNode_;
// for defaultArchive
SharedPtr<PropertyRow> rootNode_;
std::string typeName_;
const char* derivedTypeName_;
std::string derivedTypeNameAlt_;
bool outlineMode_;
};
// vim:ts=4 sw=4:
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYOARCHIVE_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,575 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#pragma once
#if !defined(Q_MOC_RUN)
#include <typeinfo>
#include <algorithm>
#include "Serialization/Serializer.h"
#include "Serialization/StringList.h"
#include <Serialization/Pointers.h>
#include "Factory.h"
#include "ConstStringList.h"
#include "Strings.h"
#include "../EditorCommonAPI.h"
#include "Serialization/ClassFactory.h"
#include <QObject>
#include <QPoint>
#include <QRect>
#include <QCursor>
#endif
namespace Serialization { struct ICallback; }
class QWidget;
class QFont;
class QPainter;
class QMenu;
class QKeyEvent;
using std::vector;
class QPropertyTree;
class PropertyRow;
class PropertyTreeModel;
class PopupMenuItem;
struct PropertyDrawContext;
struct EDITOR_COMMON_API ContainerMenuHandler;
class PropertyRowContainer;
enum ScanResult {
SCAN_FINISHED,
SCAN_CHILDREN,
SCAN_SIBLINGS,
SCAN_CHILDREN_SIBLINGS,
};
struct EDITOR_COMMON_API PropertyRowMenuHandler : QObject
{
public:
virtual ~PropertyRowMenuHandler() {}
};
struct PropertyActivationEvent
{
enum Reason
{
REASON_PRESS,
REASON_RELEASE,
REASON_DOUBLECLICK,
REASON_KEYBOARD,
REASON_NEW_ELEMENT
};
QPropertyTree* tree;
Reason reason;
bool force;
QPoint clickPoint;
PropertyActivationEvent()
: force(false)
, clickPoint(0, 0)
, tree(0)
, reason(REASON_PRESS)
{
}
};
struct PropertyDragEvent
{
QPropertyTree* tree;
QPoint pos;
QPoint start;
QPoint lastDelta;
QPoint totalDelta;
};
struct PropertyHoverInfo
{
QCursor cursor;
QString toolTip;
PropertyHoverInfo()
: cursor()
{
}
};
enum DragCheckBegin {
DRAG_CHECK_IGNORE,
DRAG_CHECK_SET,
DRAG_CHECK_UNSET
};
class PropertyRowWidget : public QObject
{
Q_OBJECT
public:
PropertyRowWidget(PropertyRow* row, QPropertyTree* tree);
virtual ~PropertyRowWidget();
virtual QWidget* actualWidget() { return 0; }
virtual void showPopup() {}
virtual void commit() = 0;
PropertyRow* row() { return row_; }
PropertyTreeModel* model() { return model_; }
protected:
PropertyRow* row_;
QPropertyTree* tree_;
PropertyTreeModel* model_;
};
class PropertyTreeTransaction;
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class EDITOR_COMMON_API PropertyRow : public Serialization::RefCounter
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
enum WidgetPlacement {
WIDGET_NONE,
WIDGET_ICON,
WIDGET_AFTER_NAME,
WIDGET_VALUE,
WIDGET_AFTER_PULLED,
WIDGET_INSTEAD_OF_TEXT
};
typedef std::vector< Serialization::SharedPtr<PropertyRow> > Rows;
typedef Rows::iterator iterator;
typedef Rows::const_iterator const_iterator;
PropertyRow();
virtual ~PropertyRow();
void setNames(const char* name, const char* label, const char* typeName);
bool selected() const{ return selected_; }
void setSelected(bool selected) { selected_ = selected; }
bool expanded() const{ return expanded_; }
void _setExpanded(bool expanded); // use QPropertyTree::expandRow
void setExpandedRecursive(QPropertyTree* tree, bool expanded);
void setMatchFilter(bool matchFilter) { matchFilter_ = matchFilter; }
bool matchFilter() const { return matchFilter_; }
void setBelongsToFilteredRow(bool belongs) { belongsToFilteredRow_ = belongs; }
bool belongsToFilteredRow() const { return belongsToFilteredRow_; }
bool visible(const QPropertyTree* tree) const;
bool hasVisibleChildren(const QPropertyTree* tree, bool internalCall = false) const;
const PropertyRow* hit(const QPropertyTree* tree, QPoint point) const;
PropertyRow* hit(const QPropertyTree* tree, QPoint point);
PropertyRow* parent() { return parent_; }
const PropertyRow* parent() const{ return parent_; }
void setParent(PropertyRow* row) { parent_ = row; }
bool isRoot() const { return !parent_; }
int level() const;
void add(PropertyRow* row);
void addAfter(PropertyRow* row, PropertyRow* after);
void addBefore(PropertyRow* row, PropertyRow* before);
template<class Op> bool scanChildren(Op& op);
template<class Op> bool scanChildren(Op& op, QPropertyTree* tree);
template<class Op> bool scanChildrenReverse(Op& op, QPropertyTree* tree);
template<class Op> bool scanChildrenBottomUp(Op& op, QPropertyTree* tree);
PropertyRow* childByIndex(int index);
const PropertyRow* childByIndex(int index) const;
int childIndex(const PropertyRow* row) const;
bool isChildOf(const PropertyRow* row) const;
bool empty() const{ return children_.empty(); }
iterator find(PropertyRow* row) { return std::find(children_.begin(), children_.end(), row); }
PropertyRow* findFromIndex(int* outIndex, const char* name, const char* typeName, int startIndex) const;
PropertyRow* findByAddress(const void* handle);
virtual const void* searchHandle() const;
iterator begin() { return children_.begin(); }
iterator end() { return children_.end(); }
const_iterator begin() const{ return children_.begin(); }
const_iterator end() const{ return children_.end(); }
std::size_t count() const{ return children_.size(); }
iterator erase(iterator it){ return children_.erase(it); }
void clear(){ children_.clear(); }
void erase(PropertyRow* row);
void swapChildren(PropertyRow* row, PropertyTreeModel* model);
void assignRowState(const PropertyRow& row, bool recurse);
void assignRowProperties(PropertyRow* row);
void replaceAndPreserveState(PropertyRow* oldRow, PropertyRow* newRow, PropertyTreeModel* model);
const char* name() const{ return name_; }
void setName(const char* name) { name_ = name; }
const char* label() const { return label_; }
const char* labelUndecorated() const { return labelUndecorated_; }
void setLabel(const char* label);
void setLabelChanged();
void setTooltip(const char* tooltip);
bool setValidatorEntry(int index, int count);
int validatorCount() const{ return validatorCount_; }
int validatorIndex() const{ return validatorIndex_; }
void resetValidatorIcons();
void addValidatorIcons(bool hasWarnings, bool hasErrors);
const char* tooltip() const { return tooltip_; }
void setLayoutChanged();
void setLabelChangedToChildren();
void setLayoutChangedToChildren();
void setHideChildren(bool hideChildren) { hideChildren_ = hideChildren; }
bool hideChildren() const { return hideChildren_; }
void updateLabel(const QPropertyTree* tree, int index, bool parentHidesNonInlineChildren);
void updateTextSizeInitial(const QPropertyTree* tree, int index, bool force);
virtual void labelChanged() {}
void parseControlCodes(const QPropertyTree* tree, const char* label, bool changeLabel);
const char* typeName() const{ return typeName_; }
virtual const char* typeNameForFilter(QPropertyTree* tree) const;
void setTypeName(const char* typeName) { typeName_ = typeName; }
const char* rowText(char* containerLabelBuffer, size_t bufsiz, const QPropertyTree* tree, int rowIndex) const;
PropertyRow* findSelected();
PropertyRow* find(const char* name, const char* nameAlt, const char* typeName);
const PropertyRow* find(const char* name, const char* nameAlt, const char* typeName) const;
void intersect(const PropertyRow* row);
int verticalIndex(QPropertyTree* tree, PropertyRow* row);
PropertyRow* rowByVerticalIndex(QPropertyTree* tree, int index);
int horizontalIndex(QPropertyTree* tree, PropertyRow* row);
PropertyRow* rowByHorizontalIndex(QPropertyTree* tree, int index);
virtual bool assignToPrimitive([[maybe_unused]] void* object, [[maybe_unused]] size_t size) const{ return false; }
virtual bool assignTo([[maybe_unused]] const Serialization::SStruct& ser) const{ return false; }
virtual bool assignToByPointer(void* instance, const Serialization::TypeID& type) const{ return assignTo(Serialization::SStruct(type, instance, type.sizeOf(), 0)); }
virtual void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) { serializer_ = ser; }
virtual void handleChildrenChange() {}
virtual string valueAsString() const;
virtual wstring valueAsWString() const;
int height() const{ return size_.y(); }
virtual int widgetSizeMin(const QPropertyTree*) const { return userWidgetSize() >= 0 ? userWidgetSize() : 0; }
virtual int floorHeight() const{ return 0; }
void calcPulledRows(int* minTextSize, int* freePulledChildren, int* minimalWidth, const QPropertyTree* tree, int index);
void calculateMinimalSize(const QPropertyTree* tree, int posX, int availableWidth, bool force, int* extraSizeRemainder, int* _extraSize, int index);
void setTextSize(const QPropertyTree* tree, int rowIndex, float multiplier);
void calculateTotalSizes(int* minTextSize);
void adjustVerticalPosition(const QPropertyTree* tree, int& totalHeight);
virtual bool isWidgetFixed() const{ return userFixedWidget_ || (widgetPlacement() != WIDGET_VALUE && widgetPlacement() != WIDGET_INSTEAD_OF_TEXT); }
virtual WidgetPlacement widgetPlacement() const{ return WIDGET_NONE; }
QRect rect() const{ return QRect(pos_.x(), pos_.y(), size_.x(), size_.y()); }
QRect rectIncludingChildren(const QPropertyTree* tree) const;
QRect textRect(const QPropertyTree* tree) const;
QRect widgetRect(const QPropertyTree* tree) const;
QRect plusRect(const QPropertyTree* tree) const;
QRect floorRect(const QPropertyTree* tree) const;
QRect validatorRect(const QPropertyTree* tree) const;
QRect validatorWarningIconRect(const QPropertyTree* tree) const;
QRect validatorErrorIconRect(const QPropertyTree* tree) const;
void adjustHoveredRect(QRect& hoveredRect);
int heightIncludingChildren() const{ return heightIncludingChildren_; }
const QFont* rowFont(const QPropertyTree* tree) const;
void drawRow(QPainter& painter, const QPropertyTree* tree, int rowIndex, bool selectionPass);
void drawPlus(QPainter& p, const QPropertyTree* tree, const QRect& rect, bool expanded, bool selected, bool grayed) const;
void drawStaticText(QPainter& p, const QRect& widgetRect);
virtual void redraw(const PropertyDrawContext& context);
virtual PropertyRowWidget* createWidget([[maybe_unused]] QPropertyTree* tree) { return 0; }
virtual bool isContainer() const{ return false; }
virtual bool isPointer() const{ return false; }
virtual bool isObject() const{ return false; }
virtual bool isLeaf() const{ return false; }
virtual void closeNonLeaf([[maybe_unused]] const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) {}
virtual bool isStatic() const{ return pulledContainer_ == 0; }
virtual bool isSelectable() const{ return (!userReadOnly() && !userReadOnlyRecurse()) || (!pulledUp() && !pulledBefore()); }
virtual bool activateOnAdd() const{ return false; }
virtual bool inlineInShortArrays() const{ return false; }
bool canBeToggled(const QPropertyTree* tree) const;
bool canBeDragged() const;
bool canBeDroppedOn(const PropertyRow* parentRow, const PropertyRow* beforeChild, const QPropertyTree* tree) const;
void dropInto(PropertyRow* parentRow, PropertyRow* cursorRow, QPropertyTree* tree, bool before);
virtual bool getHoverInfo(PropertyHoverInfo* hit, [[maybe_unused]] const QPoint& cursorPos, [[maybe_unused]] const QPropertyTree* tree) const {
hit->toolTip = QString::fromUtf8(tooltip_);
return true;
}
virtual bool onActivate(const PropertyActivationEvent& e);
virtual bool processesKey(QPropertyTree* tree, const QKeyEvent* ev); // returns true if it wants to process key events; otherwise, they will get processed by shortcuts in some cases, like delete
virtual bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev);
virtual bool onMouseDown([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point, [[maybe_unused]] bool& changed) { return false; }
virtual void onMouseDrag([[maybe_unused]] const PropertyDragEvent& e) {}
virtual void onMouseStill([[maybe_unused]] const PropertyDragEvent& e) {}
virtual void onMouseUp([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] QPoint point) {}
// "drag check" allows you to "paint" with the mouse through checkboxes to set all values at once
virtual DragCheckBegin onMouseDragCheckBegin() { return DRAG_CHECK_IGNORE; }
virtual bool onMouseDragCheck([[maybe_unused]] QPropertyTree* tree, [[maybe_unused]] bool value) { return false; }
virtual bool onContextMenu(QMenu &menu, QPropertyTree* tree);
virtual ContainerMenuHandler* createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container);
virtual bool isFullRow(const QPropertyTree* tree) const;
// User states.
// Assigned using control codes (characters in the beginning of label)
// fixed widget doesn't expand automatically to occupy all available place
bool userFixedWidget() const{ return userFixedWidget_; }
bool userFullRow() const { return userFullRow_; }
void setUserReadOnly(bool userReadOnly) { userReadOnly_ = userReadOnly; }
virtual bool userReadOnly() const { return userReadOnly_; }
void propagateFlagsTopToBottom();
virtual bool userReadOnlyRecurse() const { return userReadOnlyRecurse_; }
bool userWidgetToContent() const { return userWidgetToContent_; }
int userWidgetSize() const{ return userWidgetSize_; }
bool userNonCopyable() const { return userNonCopyable_; }
// multiValue is used to edit properties of multiple objects simulateneously
bool multiValue() const { return multiValue_; }
void setMultiValue(bool multiValue) { multiValue_ = multiValue; }
// pulledRow - is the one that is pulled up to the parents row
// (created with ^ in the beginning of label)
bool pulledUp() const { return pulledUp_; }
bool pulledBefore() const { return pulledBefore_; }
bool hasPulled() const { return hasPulled_; }
bool packedAfterPreviousRow() const { return packedAfterPreviousRow_; }
bool pulledSelected() const;
PropertyRow* nonPulledParent();
void setPulledContainer(PropertyRow* container){ pulledContainer_ = container; }
PropertyRow* pulledContainer() { return pulledContainer_; }
const PropertyRow* pulledContainer() const{ return pulledContainer_; }
Serialization::SharedPtr<PropertyRow> clone(ConstStringList* constStrings) const;
Serialization::SStruct serializer() const{ return serializer_; }
virtual Serialization::TypeID typeId() const{ return serializer_.type(); }
void setSerializer(const Serialization::SStruct& ser) { serializer_ = ser; }
virtual void serializeValue([[maybe_unused]] Serialization::IArchive& ar) {}
void setCallback(Serialization::ICallback* callback);
Serialization::ICallback* callback() { return callback_; }
virtual void Serialize(Serialization::IArchive& ar);
static void setConstStrings(ConstStringList* constStrings){ constStrings_ = constStrings; }
protected:
void init(const char* name, const char* nameAlt, const char* typeName);
PropertyRow* findChildFromDescendant(PropertyRow* row) const;
virtual void overrideTextColor([[maybe_unused]] QColor& textColor) {}
const char* name_;
const char* label_;
const char* labelUndecorated_;
const char* typeName_;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
Serialization::SStruct serializer_;
PropertyRow* parent_;
Serialization::ICallback* callback_;
const char* tooltip_;
Rows children_;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
unsigned int textHash_;
// do we really need QPoint here?
QPoint pos_;
QPoint size_;
short int textPos_;
short int textSizeInitial_;
short int textSize_;
short int widgetPos_; // widget == icon!
short int widgetSize_;
short int userWidgetSize_;
unsigned short heightIncludingChildren_;
unsigned short validatorIndex_;
unsigned short validatorsHeight_;
unsigned char validatorCount_;
unsigned char plusSize_;
bool visible_ : 1;
bool matchFilter_ : 1;
bool belongsToFilteredRow_ : 1;
bool expanded_ : 1;
bool selected_ : 1;
bool labelChanged_ : 1;
bool layoutChanged_ : 1;
bool userReadOnly_ : 1;
bool userReadOnlyRecurse_ : 1;
bool userFixedWidget_ : 1;
bool userFullRow_ : 1;
bool userPackCheckboxes_ : 1;
bool userWidgetToContent_ : 1;
bool pulledUp_ : 1;
bool pulledBefore_ : 1;
bool packedAfterPreviousRow_ : 1;
bool hasPulled_ : 1;
bool multiValue_ : 1;
bool hideChildren_ : 1;
bool validatorHasErrors_ : 1;
bool validatorHasWarnings_ : 1;
bool userNonCopyable_ : 1;
enum class FontWeight
{
Undefined,
Bold,
Regular
};
FontWeight fontWeight_;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
Serialization::SharedPtr<PropertyRow> pulledContainer_;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
static ConstStringList* constStrings_;
friend class PropertyOArchive;
friend class PropertyIArchive;
};
inline unsigned int calculateHash(const char* str, unsigned hash = 5381)
{
while(*str)
hash = hash * 33 + (unsigned char)*str++;
return hash;
}
template<class T>
inline unsigned int calculateHash(const T& t, unsigned hash = 5381)
{
for (int i = 0; i < sizeof(T); i++)
hash = hash * 33 + ((unsigned char*)&t)[i];
return hash;
}
struct RowWidthCache
{
unsigned int valueHash;
int width;
RowWidthCache() : valueHash(0), width(-1) {}
int getOrUpdate(const QPropertyTree* tree, const PropertyRow* rowForValue, int extraSpace);
};
typedef vector<Serialization::SharedPtr<PropertyRow> > PropertyRows;
template<bool value>
struct StaticBool{
enum { Value = value };
};
struct LessStrCmp
{
bool operator()(const char* a, const char* b) const {
return strcmp(a, b) < 0;
}
};
typedef Factory<const char*, PropertyRow, LessStrCmp> PropertyRowFactory;
template<class Op>
bool PropertyRow::scanChildren(Op& op)
{
Rows::iterator it;
for(it = children_.begin(); it != children_.end(); ++it){
ScanResult result = op(*it);
if(result == SCAN_FINISHED)
return false;
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
if(!(*it)->scanChildren(op))
return false;
if(result == SCAN_CHILDREN)
return false;
}
}
return true;
}
template<class Op>
bool PropertyRow::scanChildren(Op& op, QPropertyTree* tree)
{
int numChildren = int(children_.size());
for(int index = 0; index < numChildren; ++index){
PropertyRow* child = children_[index];
ScanResult result = op(child, tree, index);
if(result == SCAN_FINISHED)
return false;
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
if(!child->scanChildren(op, tree))
return false;
if(result == SCAN_CHILDREN)
return false;
}
}
return true;
}
template<class Op>
bool PropertyRow::scanChildrenReverse(Op& op, QPropertyTree* tree)
{
int numChildren = (int)children_.size();
for(int index = numChildren - 1; index >= 0; --index){
PropertyRow* child = children_[index];
ScanResult result = op(child, tree, index);
if(result == SCAN_FINISHED)
return false;
if(result == SCAN_CHILDREN || result == SCAN_CHILDREN_SIBLINGS){
if(!child->scanChildrenReverse(op, tree))
return false;
if(result == SCAN_CHILDREN)
return false;
}
}
return true;
}
template<class Op>
bool PropertyRow::scanChildrenBottomUp(Op& op, QPropertyTree* tree)
{
size_t numChildren = children_.size();
for(size_t i = 0; i < numChildren; ++i)
{
PropertyRow* child = children_[i];
if(!child->scanChildrenBottomUp(op, tree))
return false;
ScanResult result = op(child, tree);
if(result == SCAN_FINISHED)
return false;
}
return true;
}
EDITOR_COMMON_API PropertyRowFactory& GlobalPropertyRowFactory();
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GlobalPropertyRowClassFactory();
struct PropertyRowPtrSerializer : Serialization::SharedPtrSerializer<PropertyRow>
{
PropertyRowPtrSerializer(Serialization::SharedPtr<PropertyRow>& ptr) : SharedPtrSerializer(ptr) {}
Serialization::ClassFactory<PropertyRow>* factory() const override { return &GlobalPropertyRowClassFactory(); }
};
inline bool Serialize(Serialization::IArchive& ar, Serialization::SharedPtr<PropertyRow>& ptr, const char* name, const char* label)
{
PropertyRowPtrSerializer serializer(ptr);
return ar(static_cast<Serialization::IPointer&>(serializer), name, label);
}
#define REGISTER_PROPERTY_ROW(DataType, RowType) \
PropertyRow* _Factory_For_##RowType() {return new RowType; }; \
REGISTER_IN_FACTORY(PropertyRowFactory, Serialization::TypeID::get<DataType>().name(), RowType, _Factory_For_##RowType); \
SERIALIZATION_CLASS_NAME_FOR_FACTORY(GlobalPropertyRowClassFactory(), PropertyRow, RowType, #DataType, #DataType);
// Exposes the necessary class factories to extend the property tree
// Exposes the necessary class factories to extend the property tree
EDITOR_COMMON_API Serialization::ClassFactory<PropertyRow>& GetPropertyRowClassFactory();
EDITOR_COMMON_API PropertyRowFactory& GetPropertyRowFactory();
@@ -0,0 +1,168 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "platform.h"
#include <QIcon>
#include "Serialization/ClassFactory.h"
#include "PropertyDrawContext.h"
#include "PropertyRowImpl.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "Serialization.h"
#include "Color.h"
#include "Unicode.h"
#include "Serialization/Decorators/ActionButton.h"
using Serialization::IActionButton;
using Serialization::IActionButtonPtr;
class PropertyRowActionButton
: public PropertyRow
{
public:
PropertyRowActionButton()
: underMouse_()
, pressed_()
, minimalWidth_() {}
bool isLeaf() const override { return true; }
bool isStatic() const override { return false; }
bool isSelectable() const override { return true; }
bool onActivate(const PropertyActivationEvent& e) override
{
if (e.reason == PropertyActivationEvent::REASON_KEYBOARD)
{
if (value_)
{
value_->Callback();
}
}
return true;
}
bool onMouseDown(QPropertyTree* tree, QPoint point, [[maybe_unused]] bool& changed) override
{
if (userReadOnly())
{
return false;
}
if (widgetRect(tree).contains(point))
{
underMouse_ = true;
pressed_ = true;
tree->update();
return true;
}
return false;
}
void onMouseDrag(const PropertyDragEvent& e) override
{
if (userReadOnly())
{
return;
}
bool underMouse = widgetRect(e.tree).contains(e.pos);
if (underMouse != underMouse_)
{
underMouse_ = underMouse;
e.tree->update();
}
}
void onMouseUp(QPropertyTree* tree, QPoint point) override
{
if (userReadOnly())
{
return;
}
if (widgetRect(tree).contains(point))
{
pressed_ = false;
if (value_)
{
value_->Callback();
}
tree->update();
}
}
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override
{
value_ = static_cast<IActionButton*>(ser.pointer())->Clone();
const char* icon = value_->Icon();
icon_ = icon && icon[0] ? QIcon() : QIcon(QString::fromLocal8Bit(icon));
}
bool assignTo([[maybe_unused]] const Serialization::SStruct& ser) const override { return true; }
wstring valueAsWString() const override { return L""; }
WidgetPlacement widgetPlacement() const override { return WIDGET_INSTEAD_OF_TEXT; }
void serializeValue([[maybe_unused]] Serialization::IArchive& ar) override { }
int widgetSizeMin(const QPropertyTree* tree) const override
{
if (minimalWidth_ == 0)
{
QFontMetrics fm(tree->font());
minimalWidth_ = (int)fm.horizontalAdvance(QString::fromLocal8Bit(labelUndecorated())) + 6 + (icon_.isNull() ? 0 : 18);
}
return minimalWidth_;
}
void redraw(const PropertyDrawContext& context)
{
QRect rect = context.widgetRect.adjusted(-1, -1, 1, 1);
bool pressed = pressed_ && underMouse_;
wstring text = toWideChar(labelUndecorated());
if (icon_.isNull())
{
int buttonFlags = BUTTON_CENTER;
if (pressed)
{
buttonFlags |= BUTTON_PRESSED;
}
if (selected())
{
buttonFlags |= BUTTON_FOCUSED;
}
if (userReadOnly())
{
buttonFlags |= BUTTON_DISABLED;
}
context.drawButton(rect, text.c_str(), buttonFlags, &context.tree->font());
}
else
{
context.drawButtonWithIcon(icon_, rect, text.c_str(), selected(), pressed, selected(), !userReadOnly(), true, &context.tree->font());
}
}
bool isFullRow(const QPropertyTree* tree) const override
{
if (PropertyRow::isFullRow(tree))
{
return true;
}
return !userFixedWidget();
}
protected:
mutable int minimalWidth_;
bool underMouse_;
bool pressed_;
QIcon icon_;
IActionButtonPtr value_;
};
REGISTER_PROPERTY_ROW(IActionButton, PropertyRowActionButton);
@@ -0,0 +1,116 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "PropertyRowBool.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "PropertyDrawContext.h"
#include "Serialization/ClassFactory.h"
#include "Serialization.h"
#include <QKeyEvent>
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowBool, "PropertyRowBool", "bool");
PropertyRowBool::PropertyRowBool()
: value_(false)
{
}
bool PropertyRowBool::assignToPrimitive(void* object, [[maybe_unused]] size_t size) const
{
YASLI_ASSERT(size == sizeof(bool));
*reinterpret_cast<bool*>(object) = value_;
return true;
}
bool PropertyRowBool::assignToByPointer(void* instance, const Serialization::TypeID& type) const
{
return assignToPrimitive(instance, type.sizeOf());
}
void PropertyRowBool::redraw(const PropertyDrawContext& context)
{
context.drawCheck(widgetRect(context.tree), userReadOnly(), multiValue() ? CHECK_IN_BETWEEN : (value_ ? CHECK_SET : CHECK_NOT_SET));
}
bool PropertyRowBool::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
{
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Space))
{
return true;
}
return PropertyRow::processesKey(tree, ev);
}
bool PropertyRowBool::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
{
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Space))
{
PropertyActivationEvent e;
e.tree = tree;
e.reason = e.REASON_KEYBOARD;
onActivate(e);
return true;
}
return PropertyRow::onKeyDown(tree, ev);
}
bool PropertyRowBool::onActivate(const PropertyActivationEvent& e)
{
if (e.reason != e.REASON_RELEASE)
{
if (!this->userReadOnly())
{
e.tree->model()->rowAboutToBeChanged(this);
value_ = !value_;
e.tree->model()->rowChanged(this);
return true;
}
}
return false;
}
DragCheckBegin PropertyRowBool::onMouseDragCheckBegin()
{
if (userReadOnly())
{
return DRAG_CHECK_IGNORE;
}
return value_ ? DRAG_CHECK_UNSET : DRAG_CHECK_SET;
}
bool PropertyRowBool::onMouseDragCheck(QPropertyTree* tree, bool value)
{
if (value_ != value)
{
tree->model()->rowAboutToBeChanged(this);
value_ = value;
tree->model()->rowChanged(this);
return true;
}
return false;
}
void PropertyRowBool::serializeValue(Serialization::IArchive& ar)
{
ar(value_, "value", "Value");
}
int PropertyRowBool::widgetSizeMin(const QPropertyTree* tree) const
{
return aznumeric_cast<int>(tree->_defaultRowHeight() * 0.9f);
}
@@ -0,0 +1,50 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
#pragma once
#include "PropertyRow.h"
#include "Unicode.h"
class PropertyRowBool
: public PropertyRow
{
public:
PropertyRowBool();
bool assignToPrimitive(void* val, size_t size) const override;
bool assignToByPointer(void* instance, const Serialization::TypeID& type) const;
void setValue(bool value, const void* handle, [[maybe_unused]] const Serialization::TypeID& typeId) { value_ = value; serializer_.setPointer((void*)handle); serializer_.setType(Serialization::TypeID::get<bool>()); }
void redraw(const PropertyDrawContext& context);
bool isLeaf() const{ return true; }
bool isStatic() const{ return false; }
bool onActivate(const PropertyActivationEvent& e);
DragCheckBegin onMouseDragCheckBegin() override;
bool onMouseDragCheck(QPropertyTree* tree, bool value) override;
wstring valueAsWString() const{ return value_ ? L"true" : L"false"; }
string valueAsString() const{ return value_ ? "true" : "false"; }
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
void serializeValue(Serialization::IArchive& ar);
int widgetSizeMin(const QPropertyTree* tree) const override;
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev) override;
protected:
bool value_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWBOOL_H
@@ -0,0 +1,241 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "PropertyRowColor.h"
#include "Serialization/ClassFactory.h"
#include <Cry_Color.h>
#include <QMenu>
#include <QFileDialog>
#include <QPainter>
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
#include <AzQtComponents/Utilities/Conversions.h>
using Serialization::Vec3AsColor;
typedef SerializableColor_tpl<unsigned char> SerializableColorB;
typedef SerializableColor_tpl<float> SerializableColorF;
QColor ToQColor(const ColorB& v)
{
return QColor(v.r, v.g, v.b, v.a);
}
void FromQColor(SerializableColorB& vColor, QColor color)
{
vColor.r = color.red();
vColor.g = color.green();
vColor.b = color.blue();
vColor.a = color.alpha();
}
QColor ToQColor(const Vec3AsColor& v)
{
return QColor(int(v.v.x * 255.0f), int(v.v.y * 255.0f), int(v.v.z * 255.0f));
}
void FromQColor(Vec3AsColor& vColor, QColor color)
{
vColor.v.x = color.red() / 255.0f;
vColor.v.y = color.green() / 255.0f;
vColor.v.z = color.blue() / 255.0f;
}
QColor ToQColor(const SerializableColorF& v)
{
return QColor::fromRgbF(v.r, v.g, v.b, v.a);
}
void FromQColor(SerializableColorF& vColor, QColor color)
{
vColor.r = aznumeric_cast<float>(color.redF());
vColor.g = aznumeric_cast<float>(color.greenF());
vColor.b = aznumeric_cast<float>(color.blueF());
vColor.a = aznumeric_cast<float>(color.alphaF());
}
template <class ColorClass>
bool PropertyRowColor<ColorClass>::pickColor(QPropertyTree* tree)
{
const AZ::Color initialColor = AzQtComponents::fromQColor(color_);
const AZ::Color color = AzQtComponents::ColorPicker::getColor(AzQtComponents::ColorPicker::Configuration::RGB, initialColor, QObject::tr("Select Color"));
if (color != initialColor)
{
tree->model()->rowAboutToBeChanged(this);
color_.setRed(color.GetR8());
color_.setGreen(color.GetG8());
color_.setBlue(color.GetB8());
colorChanged_ = true;
tree->model()->rowChanged(this);
return true;
}
return false;
}
template <class ColorClass>
bool PropertyRowColor<ColorClass>::onActivate(const PropertyActivationEvent& e)
{
return pickColor(e.tree);
}
template <class ColorClass>
void PropertyRowColor<ColorClass>::setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] IArchive& ar)
{
color_ = ToQColor(*(ColorClass*)ser.pointer());
colorChanged_ = false;
}
template <class ColorClass>
bool PropertyRowColor<ColorClass>::assignTo(const Serialization::SStruct& ser) const
{
FromQColor(*((ColorClass*)ser.pointer()), color_);
return true;
}
template<class ColorClass>
string PropertyRowColor<ColorClass>::valueAsString() const
{
char buf[64];
sprintf_s(buf, "%d %d %d", (int)color_.red(), (int)color_.green(), (int)color_.blue());
return string(buf);
}
template <class ColorClass>
bool PropertyRowColor<ColorClass>::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
Serialization::SharedPtr<PropertyRowColor> selfPointer(this);
ColorMenuHandler* handler = new ColorMenuHandler(tree, this);
menu.addAction("Pick Color", handler, SLOT(onMenuPickColor()));
tree->addMenuHandler(handler);
return true;
}
template <class ColorClass>
void PropertyRowColor<ColorClass>::redraw(const PropertyDrawContext& context)
{
static QImage checkboardPattern;
if (checkboardPattern.isNull())
{
int size = 12;
static vector<int> pixels(size * size);
for (int i = 0; i < pixels.size(); ++i)
{
pixels[i] = ((i / size) / (size / 2) + (i % size) / (size / 2)) % 2 ? 0xffffffff : 0x000000ff;
}
checkboardPattern = QImage((unsigned char*)pixels.data(), size, size, size * 4, QImage::Format_RGBA8888);
}
QRect r = context.widgetRect.adjusted(0, 0, 0, -1);
context.painter->save();
context.painter->setPen(QPen(Qt::NoPen));
context.painter->setRenderHint(QPainter::Antialiasing, true);
context.painter->setBrush(context.tree->palette().color(QPalette::Dark));
context.painter->setPen(Qt::NoPen);
context.painter->drawRoundedRect(r, 2, 2);
r = r.adjusted(1, 1, -1, -1);
QRect cr = r.adjusted(0, 0, -r.width() / 2, 0);
context.painter->setBrushOrigin(cr.topRight() + QPoint(1, 0));
context.painter->setBrush(QBrush(checkboardPattern));
context.painter->setRenderHint(QPainter::Antialiasing, false);
context.painter->drawRoundedRect(r, 2, 2);
context.painter->setPen(QPen(Qt::NoPen));
context.painter->setClipRect(cr);
context.painter->setBrush(QBrush(color_));
context.painter->drawRoundedRect(r, 2, 2);
cr = r.adjusted(r.width() / 2, 0, 0, 0);
context.painter->setClipRect(cr);
context.painter->setBrush(QBrush(QColor(color_.red(), color_.green(), color_.blue(), 255)));
context.painter->drawRoundedRect(r, 2, 2);
context.painter->restore();
}
template <class ColorClass>
void PropertyRowColor<ColorClass>::closeNonLeaf(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar)
{
color_ = ToQColor(*(ColorClass*)ser.pointer());
}
static int componentFromRowValue(const char* str, ColorB*)
{
return clamp_tpl(atoi(str), 0, 255);
}
static int componentFromRowValue(const char* str, ColorF*)
{
return clamp_tpl(int(atof(str) * 255.0f + 0.5f), 0, 255);
}
static int componentFromRowValue(const char* str, Vec3AsColor*)
{
return clamp_tpl(int(atof(str) * 255.0f + 0.5f), 0, 255);
}
template<class ColorClass>
void PropertyRowColor<ColorClass>::handleChildrenChange()
{
// generally is not needed unless we are using callbacks
PropertyRow* rows[4] = {
childByIndex(0),
childByIndex(1),
childByIndex(2),
childByIndex(3)
};
if (rows[0])
{
color_.setRed(componentFromRowValue(rows[0]->valueAsString().c_str(), (ColorClass*)0));
}
if (rows[1])
{
color_.setGreen(componentFromRowValue(rows[1]->valueAsString().c_str(), (ColorClass*)0));
}
if (rows[2])
{
color_.setBlue(componentFromRowValue(rows[2]->valueAsString().c_str(), (ColorClass*)0));
}
if (rows[3])
{
color_.setAlpha(componentFromRowValue(rows[3]->valueAsString().c_str(), (ColorClass*)0));
}
}
ColorMenuHandler::ColorMenuHandler(QPropertyTree* tree, IPropertyRowColor* propertyRowColor)
: propertyRowColor(propertyRowColor)
, tree(tree)
{
}
void ColorMenuHandler::onMenuPickColor()
{
propertyRowColor->pickColor(tree);
}
typedef PropertyRowColor<SerializableColorB> PropertyRowColorB;
typedef PropertyRowColor<Vec3AsColor> PropertyRowVec3AsColor;
typedef PropertyRowColor<SerializableColorF> PropertyRowColorF;
REGISTER_PROPERTY_ROW(SerializableColorB, PropertyRowColorB);
REGISTER_PROPERTY_ROW(Vec3AsColor, PropertyRowVec3AsColor);
REGISTER_PROPERTY_ROW(SerializableColorF, PropertyRowColorF);
#include <QPropertyTree/moc_PropertyRowColor.cpp>
@@ -0,0 +1,75 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Modifications copyright Amazon.com, Inc. or its affiliates.
#pragma once
#if !defined(Q_MOC_RUN)
#include "PropertyDrawContext.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include <Serialization.h>
#endif
struct IPropertyRowColor
{
virtual bool pickColor(QPropertyTree* tree) = 0;
};
template <class ColorClass>
class PropertyRowColor
: public PropertyRow
, public IPropertyRowColor
{
public:
PropertyRowColor()
: colorChanged_(false) {}
bool isLeaf() const override { return colorChanged_; }
bool isStatic() const override { return false; }
WidgetPlacement widgetPlacement() const{ return WIDGET_AFTER_PULLED; }
int widgetSizeMin(const QPropertyTree* tree) const { return userWidgetSize() >= 0 ? userWidgetSize() : tree->_defaultRowHeight()* 2 - 4; }
void handleChildrenChange() override;
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override;
bool assignTo(const Serialization::SStruct& ser) const override;
void closeNonLeaf(const Serialization::SStruct& ser, Serialization::IArchive& ar);
bool onActivate(const PropertyActivationEvent& ev) override;
string valueAsString() const;
void redraw(const PropertyDrawContext& context);
bool onContextMenu(QMenu& menu, QPropertyTree* tree);
bool pickColor(QPropertyTree* tree) override;
private:
QColor color_;
bool colorChanged_;
};
struct ColorMenuHandler
: PropertyRowMenuHandler
{
Q_OBJECT
public:
QPropertyTree * tree;
IPropertyRowColor* propertyRowColor;
ColorMenuHandler(QPropertyTree* tree, IPropertyRowColor* propertyRowColor);
~ColorMenuHandler(){};
public slots:
void onMenuPickColor();
};
@@ -0,0 +1,158 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorCommon_precompiled.h"
#include "PropertyRowColorPicker.h"
#include "Serialization/ClassFactory.h"
#include <IEditor.h>
#include <QMenu>
#include <QPainter>
#include <QIcon>
#include <QKeyEvent>
#include <AzQtComponents/Components/Widgets/ColorPicker.h>
#include <AzQtComponents/Utilities/Conversions.h>
bool PropertyRowColorPicker::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_RELEASE)
{
return false;
}
// ColorF -> QColor.
AZ::Color initialColor;
initialColor.SetR(color_.r);
initialColor.SetG(color_.g);
initialColor.SetB(color_.b);
initialColor.SetA(color_.a);
const AZ::Color colorFromDialog = AzQtComponents::ColorPicker::getColor(AzQtComponents::ColorPicker::Configuration::RGBA,
initialColor,
QObject::tr("Select Color"));
if (initialColor == colorFromDialog)
{
// The user cancelled the dialog box.
// Nothing more to do.
return false;
}
// QColor -> ColorF.
ColorF color(colorFromDialog.GetR(),
colorFromDialog.GetG(),
colorFromDialog.GetB(),
colorFromDialog.GetA());
e.tree->model()->rowAboutToBeChanged(this);
color_ = color;
e.tree->model()->rowChanged(this);
return true;
}
void PropertyRowColorPicker::setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar)
{
ColorPicker* value = (ColorPicker*)ser.pointer();
color_ = *value->color;
}
bool PropertyRowColorPicker::assignTo(const Serialization::SStruct& ser) const
{
((ColorPicker*)ser.pointer())->SetColor(&color_);
return true;
}
void PropertyRowColorPicker::serializeValue(Serialization::IArchive& ar)
{
ar(color_, "color");
}
const QIcon& PropertyRowColorPicker::buttonIcon([[maybe_unused]] const QPropertyTree* tree, [[maybe_unused]] int index) const
{
// Color-chip.
QColor color((int)(color_.r * 255.0f),
(int)(color_.g * 255.0f),
(int)(color_.b * 255.0f));
QPen pen(color);
QBrush brush(color);
QPixmap pixmap(16, 16);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawEllipse(0, 0, 15, 15);
static QIcon icon;
icon.addPixmap(pixmap);
return icon;
}
string PropertyRowColorPicker::valueAsString() const
{
int r = (int)(255.0f * color_.r);
int g = (int)(255.0f * color_.g);
int b = (int)(255.0f * color_.b);
int a = (int)(255.0f * color_.a);
string value;
value.Format("#%02x%02x%02x%02x", r, g, b, a);
return value;
}
void PropertyRowColorPicker::clear()
{
color_ = Col_White;
}
bool PropertyRowColorPicker::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
QAction* action = menu.addAction("Clear");
QObject::connect(action,
&QAction::triggered,
tree,
[ this, tree ]
{
tree->model()->rowAboutToBeChanged(this);
clear();
tree->model()->rowChanged(this);
});
return true;
}
bool PropertyRowColorPicker::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
{
if (QKeySequence(ev->key()) == QKeySequence(Qt::Key_Delete))
{
return true;
}
return PropertyRowField::processesKey(tree, ev);
}
bool PropertyRowColorPicker::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
{
if (ev->key() == Qt::Key_Delete)
{
tree->model()->rowAboutToBeChanged(this);
clear();
tree->model()->rowChanged(this);
return true;
}
return PropertyRowField::onKeyDown(tree, ev);
}
REGISTER_PROPERTY_ROW(ColorPicker, PropertyRowColorPicker);
DECLARE_SEGMENT(PropertyRowColorPicker)
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "PropertyDrawContext.h"
#include "PropertyRowField.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "Serialization.h"
#include <Serialization/Decorators/ColorPicker.h>
#include <Serialization/Decorators/ColorPickerImpl.h>
#include <Serialization/Decorators/IconXPM.h>
#endif
using Serialization::ColorPicker;
class PropertyRowColorPicker
: public PropertyRowField
{
public:
void clear();
bool isLeaf() const override { return true; }
bool isStatic() const override { return false; }
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override;
bool assignTo(const Serialization::SStruct& ser) const override;
bool onActivate(const PropertyActivationEvent& e) override;
int buttonCount() const override { return 1; }
virtual const QIcon& buttonIcon(const QPropertyTree* tree, int index) const override;
string valueAsString() const override;
void serializeValue(Serialization::IArchive& ar);
bool onContextMenu(QMenu& menu, QPropertyTree* tree);
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev) override;
private:
ColorF color_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCOLORPICKER_H
@@ -0,0 +1,439 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowContainer.h"
#include "PropertyRowPointer.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "PropertyDrawContext.h"
#include "Serialization.h"
#include "PropertyRowPointer.h"
#include <QMenu>
#include <QKeyEvent>
// ---------------------------------------------------------------------------
ContainerMenuHandler::ContainerMenuHandler(QPropertyTree* tree, PropertyRowContainer* container)
: element()
, container(container)
, tree(tree)
, pointerIndex(-1)
{
}
// ---------------------------------------------------------------------------
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowContainer, "PropertyRowContainer", "Container");
PropertyRowContainer::PropertyRowContainer()
: fixedSize_(false)
, elementTypeName_("")
, inlined_(false)
{
buttonLabel_[0] = '\0';
}
struct ClassMenuItemAdderRowContainer
: ClassMenuItemAdder
{
ClassMenuItemAdderRowContainer(PropertyRowContainer* row, QPropertyTree* tree, bool insert = false)
: row_(row)
, tree_(tree)
, insert_(insert) {}
void addAction(QMenu& menu, const char* text, int index) override
{
ContainerMenuHandler* handler = row_->createMenuHandler(tree_, row_);
tree_->addMenuHandler(handler);
handler->pointerIndex = index;
QAction* action = menu.addAction(text);
QObject::connect(action, SIGNAL(triggered()), handler, SLOT(onMenuAppendPointerByIndex()));
}
protected:
PropertyRowContainer* row_;
QPropertyTree* tree_;
bool insert_;
};
void PropertyRowContainer::redraw(const PropertyDrawContext& context)
{
QRect widgetRect = context.widgetRect;
if (widgetRect.width() == 0 || inlined_)
{
return;
}
QRect rt = widgetRect;
rt.adjust(0, 1, -1, -1);
QColor brushColor = context.tree->palette().button().color();
QLinearGradient gradient(rt.left(), rt.top(), rt.left(), rt.bottom());
gradient.setColorAt(0.0f, brushColor);
gradient.setColorAt(0.6f, brushColor);
gradient.setColorAt(1.0f, context.tree->palette().color(QPalette::Shadow));
QBrush brush(gradient);
const wchar_t* text = multiValue() ? L"..." : buttonLabel_;
int buttonFlags = BUTTON_CENTER | BUTTON_POPUP_ARROW;
if (userReadOnly())
{
buttonFlags |= BUTTON_DISABLED;
}
if (context.m_pressed)
{
buttonFlags |= BUTTON_PRESSED;
}
context.drawButton(rt, text, buttonFlags, &context.tree->font());
}
bool PropertyRowContainer::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_RELEASE)
{
return false;
}
if (userReadOnly())
{
return false;
}
if (inlined_)
{
return false;
}
QMenu menu;
generateMenu(menu, e.tree, true);
e.tree->_setPressedRow(this);
menu.exec(e.tree->_toScreen(QPoint(widgetPos_, pos_.y() + e.tree->_defaultRowHeight())));
e.tree->_setPressedRow(0);
return true;
}
ContainerMenuHandler* PropertyRowContainer::createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container)
{
return new ContainerMenuHandler(tree, container);
}
void PropertyRowContainer::generateMenu(QMenu& menu, QPropertyTree* tree, bool addActions)
{
ContainerMenuHandler* handler = createMenuHandler(tree, this);
tree->addMenuHandler(handler);
if (fixedSize_)
{
if (!inlined_)
{
menu.addAction("[ Fixed Size Container ]")->setEnabled(false);
}
}
else if (userReadOnly())
{
menu.addAction("[ Read Only Container ]")->setEnabled(false);
}
else
{
if (addActions)
{
PropertyRow* row = defaultRow(tree->model());
if (row && row->isPointer())
{
QMenu* createItem = menu.addMenu("Add");
menu.addSeparator();
PropertyRowPointer* pointerRow = static_cast<PropertyRowPointer*>(row);
ClassMenuItemAdderRowContainer(this, tree).generateMenu(*createItem, tree->model()->typeStringList(pointerRow->baseType()));
}
else
{
menu.addAction("Insert", handler, SLOT(onMenuAddElement()));
menu.addAction("Add", handler, SLOT(onMenuAppendElement()), Qt::Key_Insert);
}
}
if (!menu.isEmpty())
{
menu.addSeparator();
}
QAction* removeAll = menu.addAction(pulledUp() ? "Remove Children" : "Remove All");
removeAll->setShortcut(QKeySequence("Shift+Delete"));
removeAll->setEnabled(!userReadOnly());
QObject::connect(removeAll, SIGNAL(triggered()), handler, SLOT(onMenuRemoveAll()));
}
}
bool PropertyRowContainer::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
if (!menu.isEmpty())
{
menu.addSeparator();
}
generateMenu(menu, tree, true);
if (pulledUp())
{
return !menu.isEmpty();
}
return PropertyRow::onContextMenu(menu, tree);
}
void ContainerMenuHandler::onMenuRemoveAll()
{
tree->model()->rowAboutToBeChanged(container);
container->clear();
tree->model()->rowChanged(container);
}
PropertyRow* PropertyRowContainer::defaultRow(PropertyTreeModel* model)
{
PropertyRow* defaultType = model->defaultType(elementTypeName_);
//YASLI_ASSERT(defaultType);
//YASLI_ASSERT(defaultType->numRef() == 1);
return defaultType;
}
const PropertyRow* PropertyRowContainer::defaultRow(const PropertyTreeModel* model) const
{
const PropertyRow* defaultType = model->defaultType(elementTypeName_);
return defaultType;
}
void ContainerMenuHandler::onMenuAddElement()
{
container->addElement(tree, false);
}
void ContainerMenuHandler::onMenuAppendElement()
{
container->addElement(tree, true);
}
PropertyRow* PropertyRowContainer::addElement(QPropertyTree* tree, bool append)
{
tree->model()->rowAboutToBeChanged(this);
PropertyRow* defaultType = defaultRow(tree->model());
YASLI_ESCAPE(defaultType != 0, return 0);
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
if (count() == 0)
{
tree->expandRow(this);
}
if (append)
{
add(clonedRow);
}
else
{
addBefore(clonedRow, 0);
}
clonedRow->setHideChildren(tree->outlineMode());
clonedRow->setLabelChanged();
clonedRow->setLabelChangedToChildren();
setMultiValue(false);
if (expanded())
{
tree->model()->selectRow(clonedRow, true);
}
tree->expandRow(clonedRow);
TreePath path = tree->model()->pathFromRow(clonedRow);
tree->model()->rowChanged(clonedRow);
clonedRow = tree->model()->rowFromPath(path);
tree->update();
clonedRow = tree->model()->rowFromPath(path);
if (clonedRow)
{
PropertyTreeModel::Selection sel;
sel.push_back(path);
tree->model()->setSelection(sel);
if (clonedRow->activateOnAdd())
{
PropertyActivationEvent e;
e.tree = tree;
e.reason = e.REASON_NEW_ELEMENT;
clonedRow->onActivate(e);
}
}
return clonedRow;
}
void ContainerMenuHandler::onMenuAppendPointerByIndex()
{
PropertyRow* defaultType = container->defaultRow(tree->model());
PropertyRowPointer* defaultTypePointer = static_cast<PropertyRowPointer*>(defaultType);
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
if (container->count() == 0)
{
tree->expandRow(container);
}
container->add(clonedRow);
clonedRow->setLabelChanged();
clonedRow->setLabelChangedToChildren();
clonedRow->setHideChildren(tree->outlineMode());
container->setMultiValue(false);
PropertyRowPointer* clonedRowPointer = static_cast<PropertyRowPointer*>(clonedRow.get());
clonedRowPointer->setDerivedType(defaultTypePointer->derivedTypeName(), defaultTypePointer->factory());
clonedRowPointer->setBaseType(defaultTypePointer->baseType());
clonedRowPointer->setFactory(defaultTypePointer->factory());
if (container->expanded())
{
tree->model()->selectRow(clonedRow, true);
}
tree->expandRow(clonedRowPointer);
PropertyTreeModel::Selection sel = tree->model()->selection();
CreatePointerMenuHandler handler;
handler.tree = tree;
handler.row = clonedRowPointer;
handler.index = pointerIndex;
handler.onMenuCreateByIndex();
tree->model()->setSelection(sel);
tree->update();
}
void ContainerMenuHandler::onMenuChildInsertBefore()
{
tree->model()->rowAboutToBeChanged(container);
PropertyRow* defaultType = tree->model()->defaultType(container->elementTypeName());
if (!defaultType)
{
return;
}
SharedPtr<PropertyRow> clonedRow = defaultType->clone(tree->model()->constStrings());
clonedRow->setHideChildren(tree->outlineMode());
element->setSelected(false);
container->addBefore(clonedRow, element);
container->setMultiValue(false);
tree->model()->selectRow(clonedRow, true);
PropertyTreeModel::Selection sel = tree->model()->selection();
tree->model()->rowChanged(clonedRow);
tree->model()->setSelection(sel);
tree->update();
clonedRow = tree->selectedRow();
if (clonedRow->activateOnAdd())
{
PropertyActivationEvent e;
e.tree = tree;
e.reason = PropertyActivationEvent::REASON_NEW_ELEMENT;
clonedRow->onActivate(e);
}
}
void ContainerMenuHandler::onMenuChildRemove()
{
tree->model()->rowAboutToBeChanged(container);
container->erase(element);
container->setMultiValue(false);
tree->model()->rowChanged(container);
}
void PropertyRowContainer::labelChanged()
{
swprintf(buttonLabel_, sizeof(buttonLabel_) / sizeof(buttonLabel_[0]), L"%zi", count());
}
void PropertyRowContainer::serializeValue(IArchive& ar)
{
ar(ConstStringWrapper(constStrings_, elementTypeName_), "elementTypeName", "ElementTypeName");
ar(fixedSize_, "fixedSize", "fixedSize");
}
string PropertyRowContainer::valueAsString() const
{
char buf[32] = { 0 };
sprintf_s(buf, "%d", (int)children_.size());
return string(buf);
}
const char* PropertyRowContainer::typeNameForFilter(QPropertyTree* tree) const
{
const PropertyRow* defaultType = defaultRow(tree->model());
if (defaultType)
{
return defaultType->typeNameForFilter(tree);
}
else
{
return elementTypeName_;
}
}
bool PropertyRowContainer::processesKeyContainer([[maybe_unused]] QPropertyTree* tree, const QKeyEvent* ev)
{
if (ev->key() == Qt::Key_Delete && ev->modifiers() == Qt::SHIFT)
{
return true;
}
if (ev->key() == Qt::Key_Insert && ev->modifiers() == Qt::NoModifier)
{
return true;
}
return false;
}
bool PropertyRowContainer::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
{
if (processesKeyContainer(tree, ev))
{
return true;
}
return PropertyRow::processesKey(tree, ev);
}
bool PropertyRowContainer::onKeyDownContainer(QPropertyTree* tree, const QKeyEvent* ev)
{
if (userReadOnly())
{
return false;
}
std::unique_ptr<ContainerMenuHandler> handler(createMenuHandler(tree, this));
if (ev->key() == Qt::Key_Delete && ev->modifiers() == Qt::SHIFT)
{
handler->onMenuRemoveAll();
return true;
}
if (ev->key() == Qt::Key_Insert && ev->modifiers() == Qt::NoModifier)
{
handler->onMenuAppendElement();
return true;
}
return false;
}
bool PropertyRowContainer::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
{
if (onKeyDownContainer(tree, ev))
{
return true;
}
return PropertyRow::onKeyDown(tree, ev);
}
int PropertyRowContainer::widgetSizeMin(const QPropertyTree* tree) const
{
return inlined_ ? 0 : (userWidgetSize() >= 0 ? userWidgetSize() : aznumeric_cast<int>(tree->_defaultRowHeight() * 1.7f));
}
#include <QPropertyTree/moc_PropertyRowContainer.cpp>
@@ -0,0 +1,96 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "PropertyRow.h"
#endif
class EDITOR_COMMON_API PropertyRowContainer;
struct EDITOR_COMMON_API ContainerMenuHandler
: PropertyRowMenuHandler
{
Q_OBJECT
public:
QPropertyTree * tree;
PropertyRowContainer* container;
PropertyRow* element;
int pointerIndex;
ContainerMenuHandler(QPropertyTree* tree, PropertyRowContainer* container);
public slots:
virtual void onMenuAddElement();
virtual void onMenuAppendElement();
virtual void onMenuAppendPointerByIndex();
virtual void onMenuRemoveAll();
virtual void onMenuChildInsertBefore();
virtual void onMenuChildRemove();
};
class EDITOR_COMMON_API PropertyRowContainer
: public PropertyRow
{
public:
PropertyRowContainer();
bool isContainer() const{ return true; }
bool onActivate(const PropertyActivationEvent& e);
bool onContextMenu(QMenu& item, QPropertyTree* tree);
virtual ContainerMenuHandler* createMenuHandler(QPropertyTree* tree, PropertyRowContainer* container) override;
void redraw(const PropertyDrawContext& context);
bool processesKeyContainer(QPropertyTree* tree, const QKeyEvent* ev);
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
bool onKeyDownContainer(QPropertyTree* tree, const QKeyEvent* key);
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* key) override;
void labelChanged() override;
bool isStatic() const{ return false; }
bool isSelectable() const{ return userWidgetSize() == 0 ? false : true; }
PropertyRow* addElement(QPropertyTree* tree, bool append);
void setInlined(bool inlined) { inlined_ = inlined; }
bool isInlined() const{ return inlined_; }
PropertyRow* defaultRow(PropertyTreeModel* model);
const PropertyRow* defaultRow(const PropertyTreeModel* model) const;
void serializeValue(Serialization::IArchive& ar);
const char* elementTypeName() const{ return elementTypeName_; }
using PropertyRow::setValueAndContext;
virtual void setValueAndContext(const Serialization::IContainer& value, [[maybe_unused]] Serialization::IArchive& ar)
{
fixedSize_ = value.isFixedSize();
elementTypeName_ = value.elementType().name();
serializer_.setPointer(value.pointer());
serializer_.setType(value.containerType());
}
const char* typeNameForFilter(QPropertyTree* tree) const override;
string valueAsString() const;
// C-array is an example of fixed size container
bool isFixedSize() const{ return fixedSize_; }
WidgetPlacement widgetPlacement() const override { return inlined_ ? WIDGET_NONE : WIDGET_AFTER_NAME; }
int widgetSizeMin(const QPropertyTree* tree) const override;
protected:
virtual void generateMenu(QMenu& menu, QPropertyTree* tree, bool addActions);
const char* elementTypeName_;
wchar_t buttonLabel_[8];
bool fixedSize_;
bool inlined_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWCONTAINER_H
@@ -0,0 +1,84 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "PropertyRowField.h"
#include "PropertyDrawContext.h"
#include "QPropertyTree.h"
#include "QPropertyTreeStyle.h"
#include <QtGui/QIcon>
enum { BUTTON_SIZE = 16 };
QRect PropertyRowField::fieldRect(const QPropertyTree* tree) const
{
QRect fieldRect = widgetRect(tree);
fieldRect.setRight(fieldRect.right() - buttonCount() * BUTTON_SIZE);
return fieldRect;
}
bool PropertyRowField::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_PRESS) {
int buttonCount = this->buttonCount();
QRect buttonsRect = widgetRect(e.tree);
buttonsRect.setLeft(buttonsRect.right() - buttonCount * BUTTON_SIZE);
if (buttonsRect.contains(e.clickPoint)) {
int buttonIndex = buttonCount - (e.clickPoint.x() - buttonsRect.x()) / BUTTON_SIZE - 1;
if (buttonIndex >= 0 && buttonIndex < buttonCount)
{
if (onActivateButton(buttonIndex, e))
return true;
}
}
}
return PropertyRow::onActivate(e);
}
void PropertyRowField::redraw(const PropertyDrawContext& context)
{
int buttonCount = this->buttonCount();
int offset = 0;
for (int i = 0; i < buttonCount; ++i) {
const QIcon& icon = buttonIcon(context.tree, i);
QRect iconRect(context.widgetRect.right() - offset - BUTTON_SIZE, context.widgetRect.top(), BUTTON_SIZE, context.widgetRect.height());
icon.paint(context.painter, iconRect, Qt::AlignCenter, userReadOnly() ? QIcon::Disabled : QIcon::Normal);
offset += BUTTON_SIZE;
}
int iconSpace = offset ? offset + 2 : 0;
if(multiValue())
context.drawEntry(L" ... ", false, true, iconSpace);
else if(userReadOnly())
context.drawValueText(pulledSelected(), valueAsWString().c_str());
else
context.drawEntry(valueAsWString().c_str(), usePathEllipsis(), false, iconSpace);
}
const QIcon& PropertyRowField::buttonIcon([[maybe_unused]] const QPropertyTree* tree, [[maybe_unused]] int index) const
{
static QIcon defaultIcon;
return defaultIcon;
}
int PropertyRowField::widgetSizeMin(const QPropertyTree* tree) const
{
if (userWidgetSize() >= 0)
return userWidgetSize();
if (userWidgetToContent_)
return widthCache_.getOrUpdate(tree, this, 0);
else
return 40;
}
@@ -0,0 +1,39 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
#pragma once
#include "PropertyRow.h"
class QIcon;
class PropertyRowField : public PropertyRow
{
public:
WidgetPlacement widgetPlacement() const override{ return WIDGET_VALUE; }
int widgetSizeMin(const QPropertyTree* tree) const override;
virtual int buttonCount() const{ return 0; }
virtual const QIcon& buttonIcon(const QPropertyTree* tree, int index) const;
virtual bool usePathEllipsis() const { return false; }
virtual bool onActivateButton([[maybe_unused]] int buttonIndex, [[maybe_unused]] const PropertyActivationEvent& e) { return false; }
void redraw(const PropertyDrawContext& context) override;
bool onActivate(const PropertyActivationEvent& e) override;
protected:
QRect fieldRect(const QPropertyTree* tree) const;
void drawButtons(int* offset);
mutable RowWidthCache widthCache_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWFIELD_H
@@ -0,0 +1,119 @@
/**
* yasli - Serialization Library.
* Copyright (C) 2007-2013 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "Serialization/ClassFactory.h"
#include "PropertyDrawContext.h"
#include "PropertyRowImpl.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "Serialization.h"
#include "Color.h"
#include "Serialization/Decorators/IconXPM.h"
using Serialization::IconXPM;
using Serialization::IconXPMToggle;
class PropertyRowIconXPM : public PropertyRow{
public:
void redraw(const PropertyDrawContext& context)
{
QRect rect = context.widgetRect;
context.drawIcon(rect, icon_);
}
bool isLeaf() const{ return true; }
bool isStatic() const{ return false; }
bool isSelectable() const{ return false; }
bool onActivate([[maybe_unused]] const PropertyActivationEvent& e)
{
return false;
}
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
YASLI_ESCAPE(ser.size() == sizeof(IconXPM), return);
icon_ = *(IconXPM*)(ser.pointer());
}
wstring valueAsWString() const{ return L""; }
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
void serializeValue([[maybe_unused]] Serialization::IArchive& ar) {}
int widgetSizeMin(const QPropertyTree* tree) const override{ return tree->_defaultRowHeight(); }
int height() const{ return 16; }
protected:
IconXPM icon_;
};
class PropertyRowIconToggle : public PropertyRow{
public:
void redraw(const PropertyDrawContext& context) override
{
IconXPM& icon = value_ ? iconTrue_ : iconFalse_;
context.drawIcon(context.widgetRect, icon);
}
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
YASLI_ESCAPE(ser.size() == sizeof(IconXPMToggle), return);
const IconXPMToggle* icon = (IconXPMToggle*)(ser.pointer());
iconTrue_ = icon->iconTrue_;
iconFalse_ = icon->iconFalse_;
value_ = icon->value_;
}
bool assignTo(const Serialization::SStruct& ser) const override
{
IconXPMToggle* toggle = (IconXPMToggle*)ser.pointer();
toggle->value_ = value_;
return true;
}
bool isLeaf() const override{ return true; }
bool isStatic() const override{ return false; }
bool isSelectable() const override{ return true; }
bool onActivate(const PropertyActivationEvent& e)
{
if (e.reason != e.REASON_RELEASE)
{
e.tree->model()->rowAboutToBeChanged(this);
value_ = !value_;
e.tree->model()->rowChanged(this);
return true;
}
return false;
}
DragCheckBegin onMouseDragCheckBegin() override
{
if (userReadOnly())
return DRAG_CHECK_IGNORE;
return value_ ? DRAG_CHECK_UNSET : DRAG_CHECK_SET;
}
bool onMouseDragCheck(QPropertyTree* tree, bool value) override
{
if (value_ != value) {
tree->model()->rowAboutToBeChanged(this);
value_ = value;
tree->model()->rowChanged(this);
return true;
}
return false;
}
wstring valueAsWString() const{ return value_ ? L"true" : L"false"; }
WidgetPlacement widgetPlacement() const{ return WIDGET_ICON; }
int widgetSizeMin(const QPropertyTree* tree) const{ return tree->_defaultRowHeight(); }
int height() const{ return 16; }
IconXPM iconTrue_;
IconXPM iconFalse_;
bool value_;
};
REGISTER_PROPERTY_ROW(IconXPM, PropertyRowIconXPM);
REGISTER_PROPERTY_ROW(IconXPMToggle, PropertyRowIconToggle);
DECLARE_SEGMENT(PropertyRowIconXPM)
@@ -0,0 +1,48 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
#pragma once
#include "Serialization/STL.h"
#include "PropertyRowField.h"
#include "Serialization.h"
template<class Type>
class PropertyRowImpl;
template<class Type>
class PropertyRowImpl : public PropertyRowField{
public:
bool assignTo(const Serialization::SStruct& ser) const override {
*reinterpret_cast<Type*>(ser.pointer()) = value();
return true;
}
bool isLeaf() const override{ return true; }
bool isStatic() const override{ return false; }
void setValue(const Type& value) { value_ = value; }
Type& value() { return value_; }
const Type& value() const{ return value_; }
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override {
YASLI_ESCAPE(ser.size() == sizeof(Type), return);
value_ = *(Type*)(ser.pointer());
}
void serializeValue(Serialization::IArchive& ar) override{
ar(value_, "value", "Value");
}
protected:
Type value_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWIMPL_H
@@ -0,0 +1,152 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowLocalFrame.h"
#include <QIcon>
#include <QAction>
#include <QMenu>
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include <Serialization/Decorators/IGizmoSink.h>
#include <Serialization/Decorators/LocalFrame.h>
#include "Serialization/ClassFactory.h"
#include "PropertyDrawContext.h"
#include "Serialization.h"
#include <Serialization/Decorators/LocalFrameImpl.h>
using Serialization::LocalPosition;
void LocalFrameMenuHandler::onMenuReset()
{
self->reset(tree);
}
PropertyRowLocalFrameBase::PropertyRowLocalFrameBase()
: m_sink(0)
, m_gizmoIndex(-1)
, m_handle(0)
, m_reset(false)
{
}
PropertyRowLocalFrameBase::~PropertyRowLocalFrameBase()
{
m_sink = 0;
}
bool PropertyRowLocalFrameBase::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_RELEASE)
{
return false;
}
return false;
}
string PropertyRowLocalFrameBase::valueAsString() const
{
return string();
}
bool PropertyRowLocalFrameBase::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
Serialization::SharedPtr<PropertyRow> selfPointer(this);
LocalFrameMenuHandler* handler = new LocalFrameMenuHandler(tree, this);
QAction* action = menu.addAction("Reset", handler, SLOT(onMenuReset()));
tree->addMenuHandler(handler);
return true;
}
void PropertyRowLocalFrameBase::reset(QPropertyTree* tree)
{
tree->model()->rowAboutToBeChanged(this);
m_reset = true;
tree->model()->rowChanged(this);
}
void PropertyRowLocalFrameBase::redraw(const PropertyDrawContext& context)
{
static QIcon gizmo("Editor/Icons/animation/gizmo_location.png");
gizmo.paint(context.painter, context.widgetRect.adjusted(1, 1, 1, 1), Qt::AlignRight);
}
static void ResetTransform(Serialization::LocalPosition* l) { *l->value = ZERO; }
static void ResetTransform(Serialization::LocalOrientation* l) { *l->value = IDENTITY; }
static void ResetTransform(Serialization::LocalFrame* l) { *l->position = ZERO; *l->rotation = IDENTITY; }
template<class TLocal>
class PropertyRowLocalFrameImpl
: public PropertyRowLocalFrameBase
{
public:
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override
{
serializer_ = ser;
TLocal* value = (TLocal*)ser.pointer();
m_handle = value->handle;
m_reset = false;
if (label() && label()[0])
{
m_sink = ar.FindContext<Serialization::IGizmoSink>();
if (m_sink)
{
m_gizmoIndex = m_sink->Write(*value, m_gizmoFlags, m_handle);
}
}
}
void closeNonLeaf(const Serialization::SStruct& ser, Serialization::IArchive& ar) override
{
if (label() && label()[0] && ar.IsInput())
{
TLocal& value = *((TLocal*)ser.pointer());
if (m_sink)
{
if (m_sink->CurrentGizmoIndex() == m_gizmoIndex)
{
m_sink->Read(&value, &m_gizmoFlags, m_handle);
}
else
{
m_sink->SkipRead();
}
}
}
}
bool assignTo(const Serialization::SStruct& ser) const
{
if (m_reset)
{
TLocal& value = *((TLocal*)ser.pointer());
ResetTransform(&value);
}
return false;
}
};
typedef PropertyRowLocalFrameImpl<Serialization::LocalPosition> PropertyRowLocalPosition;
typedef PropertyRowLocalFrameImpl<Serialization::LocalOrientation> PropertyRowLocalOrientation;
typedef PropertyRowLocalFrameImpl<Serialization::LocalFrame> PropertyRowLocalFrame;
REGISTER_PROPERTY_ROW(Serialization::LocalPosition, PropertyRowLocalPosition);
REGISTER_PROPERTY_ROW(Serialization::LocalOrientation, PropertyRowLocalOrientation);
REGISTER_PROPERTY_ROW(Serialization::LocalFrame, PropertyRowLocalFrame);
#include <QPropertyTree/moc_PropertyRowLocalFrame.cpp>
@@ -0,0 +1,70 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "Serialization/Decorators/IGizmoSink.h"
#include "PropertyRowField.h"
#include "QPropertyTree.h"
#endif
struct IGizmoSink;
class PropertyRowLocalFrameBase
: public PropertyRow
{
public:
PropertyRowLocalFrameBase();
~PropertyRowLocalFrameBase();
bool isLeaf() const override { return m_reset; }
bool isStatic() const override { return false; }
bool onActivate(const PropertyActivationEvent& e) override;
WidgetPlacement widgetPlacement() const override { return WIDGET_AFTER_PULLED; }
int widgetSizeMin(const QPropertyTree* tree) const override { return tree->_defaultRowHeight(); }
string valueAsString() const override;
bool onContextMenu(QMenu& menu, QPropertyTree* tree) override;
const void* searchHandle() const override { return m_handle; }
void redraw(const PropertyDrawContext& context) override;
void reset(QPropertyTree* tree);
protected:
Serialization::IGizmoSink* m_sink;
const void* m_handle;
int m_gizmoIndex;
mutable Serialization::GizmoFlags m_gizmoFlags;
bool m_reset;
};
struct LocalFrameMenuHandler
: PropertyRowMenuHandler
{
Q_OBJECT
public:
QPropertyTree * tree;
PropertyRowLocalFrameBase* self;
LocalFrameMenuHandler(QPropertyTree* tree, PropertyRowLocalFrameBase* self)
: tree(tree)
, self(self) {}
public slots:
void onMenuReset();
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWLOCALFRAME_H
@@ -0,0 +1,43 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "Serialization.h"
#include "PropertyRowNumber.h"
#define REGISTER_NUMBER_ROW(TypeName, postfix) \
typedef PropertyRowNumber<TypeName> PropertyRow##postfix; \
typedef Serialization::RangeDecorator<TypeName> RangeDecorator##postfix; \
PropertyRow* TypeName##postfixFactory() { return new PropertyRow##postfix; }; \
REGISTER_IN_FACTORY(PropertyRowFactory, Serialization::TypeID::get<RangeDecorator##postfix>().name(), PropertyRow##postfix, TypeName##postfixFactory); \
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRow##postfix, "PropertyRow" #postfix, #TypeName);
REGISTER_NUMBER_ROW(float, Float)
REGISTER_NUMBER_ROW(double , Double)
REGISTER_NUMBER_ROW(char, Char)
REGISTER_NUMBER_ROW(int8, Int8)
REGISTER_NUMBER_ROW(uint8, Uint8)
REGISTER_NUMBER_ROW(int16, Int16)
REGISTER_NUMBER_ROW(int32, Int32)
REGISTER_NUMBER_ROW(int64, Int64)
REGISTER_NUMBER_ROW(uint16, Uint16)
REGISTER_NUMBER_ROW(uint32, Uint32)
REGISTER_NUMBER_ROW(uint64, Uint64)
#undef REGISTER_NUMBER_ROW
DECLARE_SEGMENT(PropertyRowNumber)
// ---------------------------------------------------------------------------
@@ -0,0 +1,237 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H
#pragma once
#include "QPropertyTree.h"
#include "Serialization/MemoryWriter.h"
#include "Serialization/Decorators/Range.h"
#include "PropertyRowNumberField.h"
#include <limits.h>
#include <float.h>
#include <math.h>
template<class T>
string numberAsString(T value)
{
Serialization::MemoryWriter buf;
buf << value;
return buf.c_str();
}
inline long long stringToSignedInteger(const char* str)
{
long long value;
#ifdef _MSC_VER
value = _atoi64(str);
#else
char* endptr = (char*)str;
value = strtoll(str, &endptr, 10);
#endif
return value;
}
inline unsigned long long stringToUnsignedInteger(const char* str)
{
unsigned long long value;
if (*str == '-') {
value = 0;
}
else {
#ifdef _MSC_VER
char* endptr = (char*)str;
value = _strtoui64(str, &endptr, 10);
#else
char* endptr = (char*)str;
value = strtoull(str, &endptr, 10);
#endif
}
return value;
}
template<class Output, class Input>
Output clamp(Input value, Output min, Output max)
{
if (value < Input(min))
return min;
if (value > Input(max))
return max;
return Output(value);
}
template<class Out, class In> void clampToType(Out* out, In value) { *out = clamp(value, std::numeric_limits<Out>::lowest(), std::numeric_limits<Out>::max()); }
inline void clampedNumberFromString(char* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(signed char* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(short* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(int* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(long* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(long long* value, const char* str) { clampToType(value, stringToSignedInteger(str)); }
inline void clampedNumberFromString(unsigned char* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned short* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned int* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned long* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(unsigned long long* value, const char* str) { clampToType(value, stringToUnsignedInteger(str)); }
inline void clampedNumberFromString(float* value, const char* str)
{
double v = atof(str);
if (v > FLT_MAX)
v = FLT_MAX;
if (v < -FLT_MAX)
v = -FLT_MAX;
*value = float(v);
}
inline void clampedNumberFromString(double* value, const char* str)
{
*value = atof(str);
}
template<class Type>
class PropertyRowNumber : public PropertyRowNumberField{
public:
PropertyRowNumber()
{
softMin_ = std::numeric_limits<Type>::lowest();
softMax_ = std::numeric_limits<Type>::max();
hardMin_ = std::numeric_limits<Type>::lowest();
hardMax_ = std::numeric_limits<Type>::max();
}
void setValue(Type value, const void* handle, const Serialization::TypeID& type)
{
value_ = value;
serializer_.setPointer((void*)handle);
serializer_.setType(type);
}
bool setValueFromString(const char* str) override{
Type value = value_;
clampedNumberFromString(&value_, str);
return value_ != value;
}
string valueAsString() const override
{
return numberAsString(Type(value_));
}
bool assignToPrimitive(void* object, [[maybe_unused]] size_t size) const override
{
*reinterpret_cast<Type*>(object) = value_;
return true;
}
void setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar) override
{
Serialization::RangeDecorator<Type>* range = (Serialization::RangeDecorator<Type>*)ser.pointer();
serializer_.setPointer((void*)range->value);
serializer_.setType(Serialization::TypeID::get<Type>());
value_ = *range->value;
softMin_ = range->softMin;
softMax_ = range->softMax;
hardMin_ = range->hardMin;
hardMax_ = range->hardMax;
}
bool assignTo(const Serialization::SStruct& ser) const override
{
if (ser.type() == Serialization::TypeID::get<Serialization::RangeDecorator<Type>>()) {
Serialization::RangeDecorator<Type>* range = (Serialization::RangeDecorator<Type>*)ser.pointer();
*range->value = value_;
}
else if (ser.type() == Serialization::TypeID::get<Type>()) {
*(Type*)ser.pointer() = value_;
}
return true;
}
void serializeValue(Serialization::IArchive& ar)
{
ar(value_, "value", "Value");
ar(softMin_, "softMin", "SoftMin");
ar(softMax_, "softMax", "SoftMax");
ar(hardMin_, "hardMin", "HardMin");
ar(hardMax_, "hardMax", "HardMax");
}
void startIncrement() override
{
incrementStartValue_ = value_;
}
void endIncrement(QPropertyTree* tree) override
{
if (value_ != incrementStartValue_) {
Type value = value_;
value_ = incrementStartValue_;
value_ = value;
tree->model()->rowChanged(this, true);
}
}
void incrementLog(float screenFraction, float valueFieldFraction)
{
bool bothSoftLimitsSet = (std::numeric_limits<Type>::lowest() == 0 || softMin_ != std::numeric_limits<Type>::lowest()) && softMax_ != std::numeric_limits<Type>::max();
if (bothSoftLimitsSet)
{
Type softRange = softMax_ - softMin_;
double newValue = incrementStartValue_ + softRange * valueFieldFraction;
value_ = clamp(newValue, hardMin_, hardMax_);
}
else
{
double screenFractionMultiplier = 1000.0;
if (Serialization::TypeID::get<Type>() == Serialization::TypeID::get<float>() ||
Serialization::TypeID::get<Type>() == Serialization::TypeID::get<double>())
screenFractionMultiplier = 10.0;
double startPower = log10(fabs(double(incrementStartValue_)) + 1.0) - 3.0;
double power = startPower + fabs(screenFraction) * 10.0f;
double delta = pow(10.0, power) - pow(10.0, startPower) + screenFractionMultiplier * fabs(screenFraction);
double newValue;
if (screenFraction > 0.0f)
newValue = double(incrementStartValue_) + delta;
else
newValue = double(incrementStartValue_) - delta;
#ifdef _MSC_VER
if (_isnan(newValue)) {
#else
if (isnan(newValue)) {
#endif
if (screenFraction > 0.0f)
newValue = DBL_MAX;
else
newValue = -DBL_MAX;
}
value_ = clamp(newValue, hardMin_, hardMax_);
}
}
double sliderPosition() const override
{
if ((softMin_ == std::numeric_limits<Type>::lowest() && softMax_ == std::numeric_limits<Type>::max() && softMax_ != Type(255)) || (softMin_ >= softMax_))
return 0.0;
return clamp(double(value_ - softMin_) / (softMax_ - softMin_), 0.0, 1.0);
}
protected:
Type incrementStartValue_;
Type value_;
Type softMin_;
Type softMax_;
Type hardMin_;
Type hardMax_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBER_H
@@ -0,0 +1,287 @@
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include "EditorCommon_precompiled.h"
#include "QPropertyTree.h"
#include "QPropertyTreeStyle.h"
#include "PropertyTreeModel.h"
#include "PropertyRowNumberField.h"
#include "PropertyDrawContext.h"
#include "MathUtils.h"
#include <QStyleOption>
#include <QDesktopWidget>
#include <QApplication>
#include <QPainter>
#include <QBitmap>
PropertyRowNumberField::PropertyRowNumberField()
: pressed_(false)
, dragStarted_(false)
{
}
PropertyRowWidget* PropertyRowNumberField::createWidget(QPropertyTree* tree)
{
return new PropertyRowWidgetNumber(tree->model(), this, tree);
}
QColor interpolateColor(const QColor& a, const QColor& b, float k);
void PropertyRowNumberField::redraw(const PropertyDrawContext& context)
{
if (multiValue())
context.drawEntry(L" ... ", false, true, 0);
else if (userReadOnly())
context.drawValueText(pulledSelected(), valueAsWString().c_str());
else
{
QPainter* painter = context.painter;
const QPropertyTree* tree = context.tree;
QRect rt = context.widgetRect;
rt.adjust(0, 0, 0, -1);
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
QStyleOptionFrameV2 option;
option.features = QStyleOptionFrameV2::None;
#else
QStyleOptionFrame option;
option.features = QStyleOptionFrame::None;
#endif
option.state = QStyle::State_Sunken;
// We require a widget to use as context, so that the style sheet can work.
QLineEdit widgetForContext;
option.lineWidth = tree->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, &widgetForContext);
option.midLineWidth = 0;
if (context.captured) {
option.state |= QStyle::State_HasFocus;
option.state |= QStyle::State_Active;
option.state |= QStyle::State_MouseOver;
}
else if (!userReadOnly()) {
option.state |= QStyle::State_Enabled;
}
option.rect = rt; // option.rect is the rectangle to be drawn on.
option.palette = tree->palette();
option.fontMetrics = tree->fontMetrics();
QRect textRect = tree->style()->subElementRect(QStyle::SE_LineEditContents, &option, &widgetForContext);
if (!textRect.isValid()) {
textRect = rt;
textRect.adjust(3, 1, -3, -2);
}
else {
textRect.adjust(2, 1, -2, -1);
}
widgetForContext.ensurePolished();
option.palette = widgetForContext.palette();
painter->setPen(QPen(widgetForContext.palette().color(QPalette::WindowText)));
painter->setBrush(QBrush(widgetForContext.palette().color(QPalette::Base)));
tree->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, painter, &widgetForContext);
double sliderPos = sliderPosition();
if (sliderPos != 0.0)
{
QRect r = textRect.adjusted(-2, -1, 2, 1);
QRect sliderOverlayRect(r.left(), r.top(), int(r.width() * sliderPos), r.height());
QColor sliderOverlayColor = interpolateColor(tree->palette().color(QPalette::Window), tree->palette().color(QPalette::Highlight), tree->treeStyle().sliderSaturation);
sliderOverlayColor.setAlpha(192);
painter->setBrush(QBrush(sliderOverlayColor));
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(sliderOverlayRect, 1, 1);
if (pressed_) {
painter->setPen(QColor(255, 255, 255));
painter->setBrush(QBrush(QColor(255, 255, 255)));
painter->drawLine(sliderOverlayRect.right(), sliderOverlayRect.top(), sliderOverlayRect.right(), sliderOverlayRect.bottom());
painter->setRenderHint(QPainter::Antialiasing, true);
painter->translate(0.5f, 0.5f);
int r2 = sliderOverlayRect.right();
int t = sliderOverlayRect.top();
int h = sliderOverlayRect.height();
QPoint points[3] = {
QPoint(r2 - 1 - h / 8 - h / 3, t + h / 2),
QPoint(r2 - 1 - h / 8, t + h * 1 / 4),
QPoint(r2 - 1 - h / 8, t + h * 3 / 4)
};
QPoint pointsR[3] = {
QPoint(r2 + 1 + h / 8 + h / 3, t + h / 2),
QPoint(r2 + 1 + h / 8, t + h * 1 / 4),
QPoint(r2 + 1 + h / 8, t + h * 3 / 4)
};
painter->drawPolygon(points, 3);
painter->drawPolygon(pointsR, 3);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->translate(-0.5f, -0.5f);
}
}
painter->setPen(QPen(widgetForContext.palette().color(QPalette::WindowText)));
painter->setBrush(QBrush(widgetForContext.palette().color(QPalette::Base)));
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, QString(valueAsString().c_str()));
}
}
QCursor createSliderHoverCursor()
{
QCursor arrow(Qt::ArrowCursor);
QPoint hotSpot = arrow.hotSpot();
static QImage image = arrow.pixmap().toImage();
if (image.isNull())
return QCursor(Qt::SizeHorCursor);
int w = image.width();
int h = image.height();
QImage empty(w * 2, h, QImage::Format_ARGB32);
empty.fill(Qt::transparent);
QPixmap pixmap = QPixmap::fromImage(empty);
if (pixmap.isNull())
return QCursor(Qt::SizeHorCursor);
QPainter p(&pixmap);
p.drawImage(image.width() / 2, 0, image);
p.setRenderHint(QPainter::Antialiasing, true);
QPoint points[3] = {
QPoint(w / 2 - w * 2 / 8, h / 2),
QPoint(w / 2 - w / 8, h * 3 / 8),
QPoint(w / 2 - w / 8, h * 5 / 8)
};
QPoint pointsR[3] = {
QPoint(w, h * 3 / 8),
QPoint(w, h * 5 / 8),
QPoint(w + w / 8, h / 2),
};
p.setBrush(QBrush(QColor(255, 255, 255)));
p.setPen(QPen(QColor(0, 0, 0)));
p.drawPolygon(points, 3);
p.drawPolygon(pointsR, 3);
return QCursor(pixmap, image.width() / 2 + hotSpot.x(), hotSpot.y());
}
void PropertyRowNumberField::onMouseDrag(const PropertyDragEvent& e)
{
if (!dragStarted_) {
e.tree->model()->rowAboutToBeChanged(this);
dragStarted_ = true;
}
QSize screenSize = QApplication::desktop()->screenGeometry(e.tree).size();
float relativeDelta = float(e.totalDelta.x()) / screenSize.width();
int fieldRectWidth = widgetRect(e.tree).width();
if (fieldRectWidth < 16)
fieldRectWidth = aznumeric_cast<int>(e.tree->treeSize().x() * e.tree->valueColumnWidth());
float valueFieldFraction = fieldRectWidth < FLT_EPSILON ? 0 : float(e.totalDelta.x()) / fieldRectWidth;
incrementLog(relativeDelta, valueFieldFraction);
setMultiValue(false);
}
bool PropertyRowNumberField::getHoverInfo(PropertyHoverInfo* hit, const QPoint& cursorPos, const QPropertyTree* tree) const
{
if (pressed_ && !userReadOnly())
hit->cursor = QCursor(Qt::BlankCursor);
else if (widgetRect(tree).contains(cursorPos) && !userReadOnly())
hit->cursor = QCursor(createSliderHoverCursor());
hit->toolTip = tooltip_;
return true;
}
void PropertyRowNumberField::onMouseStill(const PropertyDragEvent& e)
{
e.tree->model()->callRowCallback(this);
e.tree->apply(true);
}
bool PropertyRowNumberField::onMouseDown(QPropertyTree* tree, QPoint point, bool& changed)
{
changed = false;
if (widgetRect(tree).contains(point) && !userReadOnly()) {
startIncrement();
pressed_ = true;
return true;
}
return false;
}
void PropertyRowNumberField::onMouseUp(QPropertyTree* tree, [[maybe_unused]] QPoint point)
{
tree->unsetCursor();
pressed_ = false;
dragStarted_ = false;
// endIncrement() can cause PropertyRow to be destroy,
// so no "this" members should be accessed after the call.
endIncrement(tree);
}
bool PropertyRowNumberField::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_RELEASE || e.reason == e.REASON_DOUBLECLICK)
return e.tree->spawnWidget(this, false);
return false;
}
int PropertyRowNumberField::widgetSizeMin(const QPropertyTree* tree) const
{
if (userWidgetSize() >= 0)
return userWidgetSize();
if (userWidgetToContent())
return widthCache_.getOrUpdate(tree, this, 0);
else
return 40;
}
// ---------------------------------------------------------------------------
PropertyRowWidgetNumber::PropertyRowWidgetNumber([[maybe_unused]] PropertyTreeModel* model, PropertyRowNumberField* row, QPropertyTree* tree)
: PropertyRowWidget(row, tree)
, row_(row)
, entry_(new QLineEdit())
, tree_(tree)
{
entry_->setText(row_->valueAsString().c_str());
connect(entry_, SIGNAL(editingFinished()), this, SLOT(onEditingFinished()));
connect(entry_, &QLineEdit::textChanged, this, [this, tree] {
QFontMetrics fm(entry_->font());
int contentWidth = min((int)fm.horizontalAdvance(entry_->text()) + 8, tree->width() - entry_->x());
if (contentWidth > entry_->width())
entry_->resize(contentWidth, entry_->height());
});
entry_->selectAll();
}
void PropertyRowWidgetNumber::onEditingFinished()
{
tree_->model()->rowAboutToBeChanged(row());
string str = entry_->text().toLocal8Bit().data();
if (row_->setValueFromString(str.c_str()) || row_->multiValue())
tree_->model()->rowChanged(row());
else
tree_->_cancelWidget();
}
void PropertyRowWidgetNumber::commit()
{
if (entry_)
onEditingFinished();
}
#include <QPropertyTree/moc_PropertyRowNumberField.cpp>
@@ -0,0 +1,75 @@
// Modifications copyright Amazon.com, Inc. or its affiliates.
/**
* wWidgets - Lightweight UI Toolkit.
* Copyright (C) 2009-2011 Evgeny Andreeshchev <eugene.andreeshchev@gmail.com>
* Alexander Kotliar <alexander.kotliar@gmail.com>
*
* This code is distributed under the MIT License:
* http://www.opensource.org/licenses/MIT
*/
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBERFIELD_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBERFIELD_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "PropertyRow.h"
#include <QLineEdit>
#endif
class PropertyRowNumberField;
class PropertyRowWidgetNumber : public PropertyRowWidget
{
Q_OBJECT
public:
PropertyRowWidgetNumber(PropertyTreeModel* mode, PropertyRowNumberField* numberField, QPropertyTree* tree);
~PropertyRowWidgetNumber(){
if (entry_)
entry_->setParent(0);
entry_->deleteLater();
entry_ = 0;
}
void commit();
QWidget* actualWidget() { return entry_; }
public slots:
void onEditingFinished();
protected:
QLineEdit* entry_;
PropertyRowNumberField* row_;
QPropertyTree* tree_;
};
// ---------------------------------------------------------------------------
class PropertyRowNumberField : public PropertyRow
{
public:
PropertyRowNumberField();
WidgetPlacement widgetPlacement() const override{ return WIDGET_VALUE; }
int widgetSizeMin(const QPropertyTree* tree) const override;
PropertyRowWidget* createWidget(QPropertyTree* tree) override;
bool isLeaf() const override{ return true; }
bool isStatic() const override{ return false; }
bool inlineInShortArrays() const override{ return true; }
void redraw(const PropertyDrawContext& context) override;
bool onActivate(const PropertyActivationEvent& e) override;
bool onMouseDown(QPropertyTree* tree, QPoint point, bool& changed) override;
void onMouseUp(QPropertyTree* tree, QPoint point) override;
void onMouseDrag(const PropertyDragEvent& e) override;
void onMouseStill(const PropertyDragEvent& e) override;
bool getHoverInfo(PropertyHoverInfo* hit, const QPoint& cursorPos, const QPropertyTree* tree) const;
virtual void startIncrement() = 0;
virtual void endIncrement(QPropertyTree* tree) = 0;
virtual void incrementLog(float screenFraction, float valueFieldFraction) = 0;
virtual bool setValueFromString(const char* str) = 0;
virtual double sliderPosition() const = 0;
mutable RowWidthCache widthCache_;
bool pressed_ : 1;
bool dragStarted_ : 1;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWNUMBERFIELD_H
@@ -0,0 +1,42 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowObject.h"
#include "PropertyTreeModel.h"
PropertyRowObject::PropertyRowObject()
: model_(0)
{
}
bool PropertyRowObject::assignTo(Serialization::Object* obj)
{
if (object_.type() == obj->type())
{
*obj = object_;
return true;
}
return false;
}
PropertyRowObject::~PropertyRowObject()
{
object_ = Serialization::Object();
}
void PropertyRowObject::Serialize(Serialization::IArchive& ar)
{
PropertyRow::Serialize(ar);
}
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOBJECT_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOBJECT_H
#pragma once
#include "PropertyRow.h"
#include "Serialization/MemoryWriter.h"
#include "Serialization/Pointers.h"
#include "Serialization/Object.h"
namespace Serialization {
class IArchive;
struct SStruct;
class MemoryWriter;
};
class PropertyRowObject
: public PropertyRow
{
public:
PropertyRowObject();
~PropertyRowObject();
using PropertyRow::setValueAndContext;
using PropertyRow::assignTo;
void setValueAndContext(const Serialization::Object& obj, [[maybe_unused]] Serialization::IArchive& ar) { object_ = obj; }
void setModel(PropertyTreeModel* model) { model_ = model; }
bool isObject() const override { return true; }
bool assignTo(Serialization::Object* obj);
void Serialize(Serialization::IArchive& ar);
const Serialization::Object& object() const{ return object_; }
protected:
Serialization::Object object_;
PropertyTreeModel* model_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOBJECT_H
@@ -0,0 +1,205 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowOutputFilePath.h"
#include "Serialization/ClassFactory.h"
#include <Serialization/Decorators/IconXPM.h>
#ifndef SERIALIZATION_STANDALONE
#include <Include/EditorCoreAPI.h>
#include <Util/PathUtil.h> // for Getting game folder
#endif
#include <QFileDialog>
#include <QIcon>
#include <QMenu>
#include <QKeyEvent>
OutputFilePathMenuHandler::OutputFilePathMenuHandler(QPropertyTree* tree, PropertyRowOutputFilePath* self)
: self(self)
, tree(tree)
{
}
void OutputFilePathMenuHandler::onMenuClear()
{
tree->model()->rowAboutToBeChanged(self);
self->clear();
tree->model()->rowChanged(self);
}
QString convertMFCToQtFileFilter(QString* defaultSuffix, const char* mfcFilter)
{
// convert filter from "All Files|*.*|Text files|*.txt||"
// format into "All files (*.*);;Text Files (*.txt)"
QString filterMFC = QString::fromLocal8Bit(mfcFilter);
QStringList filterItems = filterMFC.split("|");
if (defaultSuffix && filterItems.size() > 1)
{
QString extensions = filterItems[1];
QRegExp re("\\*\\.(\\w*)");
if (extensions.indexOf(re) >= 0)
{
*defaultSuffix = re.cap(1);
}
}
QString filter;
for (int i = 0; i < int(filterItems.size()) / 2; ++i)
{
int bracketPos = filterItems[i].indexOf('(');
QString desc = bracketPos >= 0 ? filterItems[i].left(bracketPos) : filterItems[i];
int extIndex = i * 2 + 1;
if (extIndex >= filterItems.size())
{
break;
}
if (!filter.isEmpty())
{
filter += ";;";
}
filter += desc;
filter += " (";
filter += filterItems[extIndex];
filter += ")";
}
return filter;
}
bool PropertyRowOutputFilePath::onActivate(const PropertyActivationEvent& e)
{
if (e.reason == e.REASON_RELEASE)
{
return false;
}
#ifndef SERIALIZATION_STANDALONE
if (!GetIEditor())
{
return true;
}
#endif
QString title;
if (labelUndecorated())
{
title = QString("Choose file for '") + labelUndecorated() + "'";
}
else
{
title = "Choose file";
}
#ifdef SERIALIZATION_STANDALONE
QString gameFolder;
#else
QString gameFolder = QString::fromLocal8Bit(Path::GetEditingGameDataFolder().c_str());
#endif
QDir gameFolderDir(QDir::fromNativeSeparators(gameFolder));
QString defaultSuffix;
QString filter = convertMFCToQtFileFilter(&defaultSuffix, filter_.c_str());
QString existingFile = QString::fromLocal8Bit(path_.c_str());
QString existingFilePath = (existingFile.isEmpty() || QDir::isAbsolutePath(existingFile)) ? existingFile : gameFolderDir.absoluteFilePath(existingFile);
QString startFolder = QString::fromLocal8Bit(startFolder_.c_str());
// Not using QFileDialog().exec() as it implements custom file dialog that
// freezes for couple of seconds when being open. Scannign network drives?
QString result = QFileDialog::getSaveFileName(e.tree, title, existingFilePath.isEmpty() ? (gameFolder + "/" + startFolder) : existingFilePath, filter);
if (!result.isEmpty())
{
e.tree->model()->rowAboutToBeChanged(this);
QString relativeFilename = gameFolderDir.relativeFilePath(result);
path_ = relativeFilename.toLocal8Bit().data();
e.tree->model()->rowChanged(this);
}
return true;
}
void PropertyRowOutputFilePath::setValueAndContext(const Serialization::SStruct& ser, [[maybe_unused]] Serialization::IArchive& ar)
{
OutputFilePath* value = (OutputFilePath*)ser.pointer();
path_ = value->m_path->c_str();
filter_ = value->filter.c_str();
startFolder_ = value->startFolder.c_str();
handle_ = value->m_path;
}
bool PropertyRowOutputFilePath::assignTo(const Serialization::SStruct& ser) const
{
((OutputFilePath*)ser.pointer())->SetPath(path_.c_str());
return true;
}
const QIcon& PropertyRowOutputFilePath::buttonIcon(const QPropertyTree* tree, [[maybe_unused]] int index) const
{
#include "file_save.xpm"
static QIcon fileOpenIcon = QIcon(QPixmap::fromImage(*tree->_iconCache()->getImageForIcon(Serialization::IconXPM(file_save_xpm))));
return fileOpenIcon;
}
string PropertyRowOutputFilePath::valueAsString() const
{
return path_;
}
void PropertyRowOutputFilePath::clear()
{
path_.clear();
}
bool PropertyRowOutputFilePath::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
QAction* action = menu.addAction("Clear");
Serialization::SharedPtr<PropertyRow> selfPointer(this);
OutputFilePathMenuHandler* handler = new OutputFilePathMenuHandler(tree, this);
QObject::connect(action, SIGNAL(triggered()), handler, SLOT(onMenuClear()));
tree->addMenuHandler(handler);
return true;
}
void PropertyRowOutputFilePath::serializeValue(Serialization::IArchive& ar)
{
ar(path_, "path");
ar(filter_, "filter");
ar(startFolder_, "startFolder");
}
bool PropertyRowOutputFilePath::processesKey(QPropertyTree* tree, const QKeyEvent* ev)
{
if (ev->key() == Qt::Key_Delete)
{
return true;
}
return PropertyRowField::processesKey(tree, ev);
}
bool PropertyRowOutputFilePath::onKeyDown(QPropertyTree* tree, const QKeyEvent* ev)
{
if (ev->key() == Qt::Key_Delete)
{
tree->model()->rowAboutToBeChanged(this);
clear();
tree->model()->rowChanged(this);
return true;
}
return PropertyRowField::onKeyDown(tree, ev);
}
REGISTER_PROPERTY_ROW(OutputFilePath, PropertyRowOutputFilePath);
DECLARE_SEGMENT(PropertyRowOutputFilePath)
#include <QPropertyTree/moc_PropertyRowOutputFilePath.cpp>
@@ -0,0 +1,74 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOUTPUTFILEPATH_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOUTPUTFILEPATH_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "PropertyDrawContext.h"
#include "PropertyRowField.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "Serialization.h"
#include <Serialization/Decorators/OutputFilePath.h>
#include <Serialization/Decorators/OutputFilePathImpl.h>
#endif
using Serialization::OutputFilePath;
class PropertyRowOutputFilePath
: public PropertyRowField
{
public:
void clear();
bool isLeaf() const override { return true; }
bool isStatic() const override { return false; }
bool onActivate(const PropertyActivationEvent& e) override;
void setValueAndContext(const Serialization::SStruct& ser, Serialization::IArchive& ar) override;
bool assignTo(const Serialization::SStruct& ser) const override;
string valueAsString() const;
void serializeValue(Serialization::IArchive& ar);
bool onContextMenu(QMenu& menu, QPropertyTree* tree);
const void* searchHandle() const { return handle_; }
int buttonCount() const override { return 1; }
virtual const QIcon& buttonIcon(const QPropertyTree* tree, int index) const override;
virtual bool usePathEllipsis() const override { return true; }
bool processesKey(QPropertyTree* tree, const QKeyEvent* ev) override;
bool onKeyDown(QPropertyTree* tree, const QKeyEvent* ev) override;
private:
string path_;
string filter_;
string startFolder_;
const void* handle_;
};
struct OutputFilePathMenuHandler
: PropertyRowMenuHandler
{
Q_OBJECT
public:
QPropertyTree * tree;
PropertyRowOutputFilePath* self;
OutputFilePathMenuHandler(QPropertyTree* tree, PropertyRowOutputFilePath* container);
public slots:
void onMenuClear();
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWOUTPUTFILEPATH_H
@@ -0,0 +1,347 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "EditorCommon_precompiled.h"
#include "PropertyRowPointer.h"
#include "QPropertyTree.h"
#include "PropertyTreeModel.h"
#include "PropertyDrawContext.h"
#include "Serialization.h"
#include "Unicode.h"
#include <QMenu>
// ---------------------------------------------------------------------------
void ClassMenuItemAdder::generateMenu(QMenu& createItem, const StringList& comboStrings)
{
StringList::const_iterator it;
int index = 0;
for (it = comboStrings.begin(); it != comboStrings.end(); ++it)
{
StringList path;
splitStringList(&path, it->c_str(), '\\');
int level = 0;
QMenu* item = &createItem;
//createItem.addMenu(
for (int level2 = 0; level2 < int(path.size()); ++level2)
{
const char* leaf = path[level2].c_str();
if (level2 == path.size() - 1)
{
addAction(*item, leaf, index++);
}
else
{
if (QMenu* menu = item->findChild<QMenu*>(leaf))
{
item = menu;
}
else
{
item = addMenu(*item, leaf); //&item->add(leaf);
}
}
}
}
}
void ClassMenuItemAdder::addAction(QMenu& menu, const char* text, [[maybe_unused]] int index)
{
menu.addAction(text)->setEnabled(false);
}
QMenu* ClassMenuItemAdder::addMenu(QMenu& menu, const char* text)
{
QMenu* result = menu.addMenu(text);
result->setObjectName(text);
return result;
}
// ---------------------------------------------------------------------------
SERIALIZATION_CLASS_NAME(PropertyRow, PropertyRowPointer, "PropertyRowPointer", "SharedPtr");
PropertyRowPointer::PropertyRowPointer()
: factory_(0)
, searchHandle_(0)
, colorOverride_(0, 0, 0, 0)
{
}
void PropertyRowPointer::setDerivedType(const char* typeName, Serialization::IClassFactory* factory)
{
if (!factory)
{
derivedTypeName_.clear();
return;
}
derivedTypeName_ = typeName;
}
bool PropertyRowPointer::assignTo(Serialization::IPointer& ptr)
{
if (derivedTypeName_ != ptr.registeredTypeName())
{
ptr.create(derivedTypeName_.c_str());
}
return true;
}
void CreatePointerMenuHandler::onMenuCreateByIndex()
{
tree->model()->rowAboutToBeChanged(row);
if (index < 0) // NULL value
{
row->setDerivedType("", 0);
row->clear();
}
else
{
const PropertyDefaultDerivedTypeValue* defaultValue = tree->model()->defaultType(row->baseType(), index);
SharedPtr<PropertyRow> clonedDefault = defaultValue->root->clone(tree->model()->constStrings());
if (defaultValue && defaultValue->root)
{
YASLI_ASSERT(defaultValue->root->refCount() == 1);
if (useDefaultValue)
{
row->clear();
row->swapChildren(clonedDefault, 0);
}
row->setDerivedType(defaultValue->registeredName.c_str(), row->factory());
row->setLabelChanged();
row->setLabelChangedToChildren();
tree->expandRow(row);
}
else
{
row->setDerivedType("", 0);
row->clear();
}
}
tree->model()->rowChanged(row);
}
string PropertyRowPointer::valueAsString() const
{
string result;
const Serialization::TypeDescription* desc = 0;
if (factory_)
{
desc = factory_->descriptionByRegisteredName(derivedTypeName_.c_str());
}
if (desc)
{
result = desc->label();
}
else
{
result = derivedTypeName_;
}
return result;
}
wstring PropertyRowPointer::generateLabel() const
{
if (multiValue())
{
return L"...";
}
wstring str;
if (!derivedTypeName_.empty())
{
const char* textStart = derivedTypeName_.c_str();
if (factory_)
{
const Serialization::TypeDescription* desc = factory_->descriptionByRegisteredName(derivedTypeName_.c_str());
if (desc)
{
textStart = desc->label();
}
}
const char* p = textStart + strlen(textStart);
while (p > textStart)
{
if (*(p - 1) == '\\')
{
break;
}
--p;
}
str = toWideChar(p);
if (p != textStart)
{
str += L" (";
str += toWideChar(string(textStart, p - 1).c_str());
str += L")";
}
}
else
{
if (factory_)
{
str = toWideChar(factory_->nullLabel() ? factory_->nullLabel() : "[ null ]");
}
else
{
str = L"[ null ]";
}
}
return str;
}
void PropertyRowPointer::redraw(const PropertyDrawContext& context)
{
QRect widgetRect = context.widgetRect;
QRect rt = widgetRect;
rt.adjust(-1, 0, 0, 1);
wstring str = generateLabel();
const QFont* font = derivedTypeName_.empty() ? &context.tree->font() : &context.tree->_boldFont();
int buttonFlags = BUTTON_POPUP_ARROW;
if (userReadOnly())
{
buttonFlags |= BUTTON_DISABLED;
}
if (context.m_pressed)
{
buttonFlags |= BUTTON_PRESSED;
}
context.drawButton(rt, str.c_str(), buttonFlags, font, colorOverride_.a != 0 ? &colorOverride_ : 0);
}
struct ClassMenuItemAdderRowPointer
: ClassMenuItemAdder
{
ClassMenuItemAdderRowPointer(PropertyRowPointer* row, QPropertyTree* tree)
: row_(row)
, tree_(tree) {}
void addAction(QMenu& menu, const char* text, int index)
{
CreatePointerMenuHandler* handler = new CreatePointerMenuHandler;
tree_->addMenuHandler(handler);
handler->row = row_;
handler->tree = tree_;
handler->index = index;
handler->useDefaultValue = !tree_->immediateUpdate();
QAction* action = menu.addAction(text);
QObject::connect(action, SIGNAL(triggered()), handler, SLOT(onMenuCreateByIndex()));
}
protected:
PropertyRowPointer* row_;
QPropertyTree* tree_;
};
bool PropertyRowPointer::onActivate(QPropertyTree* tree, [[maybe_unused]] bool force)
{
if (userReadOnly())
{
return false;
}
QMenu menu;
ClassMenuItemAdderRowPointer(this, tree).generateMenu(menu, tree->model()->typeStringList(baseType()));
tree->_setPressedRow(this);
menu.exec(tree->_toScreen(QPoint(widgetPos_, pos_.y() + tree->_defaultRowHeight())));
tree->_setPressedRow(0);
return true;
}
bool PropertyRowPointer::onMouseDown(QPropertyTree* tree, QPoint point, bool& changed)
{
if (widgetRect(tree).contains(point))
{
if (onActivate(tree, false))
{
changed = true;
}
}
return false;
}
bool PropertyRowPointer::onContextMenu(QMenu& menu, QPropertyTree* tree)
{
if (!menu.isEmpty())
{
menu.addSeparator();
}
if (!userReadOnly())
{
QMenu* createItem = menu.addMenu("Set");
ClassMenuItemAdderRowPointer(this, tree).generateMenu(*createItem, tree->model()->typeStringList(baseType()));
}
return PropertyRow::onContextMenu(menu, tree);
}
void PropertyRowPointer::serializeValue(IArchive& ar)
{
ar(derivedTypeName_, "derivedTypeName", "Derived Type Name");
}
int PropertyRowPointer::widgetSizeMin(const QPropertyTree* tree) const
{
QFontMetrics fm(tree->_boldFont());
QString str(fromWideChar(generateLabel().c_str()).c_str());
return fm.horizontalAdvance(str) + 24;
}
static Color parseColorString(const char* str)
{
unsigned int color = 0;
if (azsscanf(str, "%x", &color) != 1)
{
return Color(0, 0, 0, 0);
}
Color result((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, 255);
return result;
}
void PropertyRowPointer::setValueAndContext(const Serialization::IPointer& ptr, [[maybe_unused]] Serialization::IArchive& ar)
{
baseType_ = ptr.baseType();
factory_ = ptr.factory();
serializer_ = ptr.serializer();
pointerType_ = ptr.pointerType();
searchHandle_ = ptr.handle();
const char* colorString = factory_->findAnnotation(ptr.registeredTypeName(), "color");
if (colorString[0] != '\0')
{
colorOverride_ = parseColorString(colorString);
}
else
{
colorOverride_ = Color(0, 0, 0, 0);
}
const Serialization::TypeDescription* desc = factory_->descriptionByRegisteredName(ptr.registeredTypeName());
if (desc)
{
derivedTypeName_ = desc->name();
}
else
{
derivedTypeName_.clear();
}
}
#include <QPropertyTree/moc_PropertyRowPointer.cpp>
// vim:ts=4 sw=4:
@@ -0,0 +1,95 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWPOINTER_H
#define CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWPOINTER_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "Color.h"
#include "Serialization/StringList.h"
using Serialization::StringList;
#include "PropertyRow.h"
#endif
class QPropertyTree;
class PropertyRowPointer;
struct CreatePointerMenuHandler
: PropertyRowMenuHandler
{
Q_OBJECT
public:
QPropertyTree * tree;
PropertyRowPointer* row;
int index;
bool useDefaultValue;
public slots:
void onMenuCreateByIndex();
};
class QMenu;
struct ClassMenuItemAdder
{
virtual void addAction(QMenu& menu, const char* text, int index);
virtual QMenu* addMenu(QMenu& menu, const char* text);
void generateMenu(QMenu& createItem, const StringList& comboStrings);
};
class PropertyRowPointer
: public PropertyRow
{
public:
PropertyRowPointer();
bool assignTo(Serialization::IPointer& ptr);
void setValueAndContext(const Serialization::IPointer& ptr, Serialization::IArchive& ar);
using PropertyRow::assignTo;
using PropertyRow::setValueAndContext;
using PropertyRow::onActivate;
Serialization::TypeID baseType() const{ return baseType_; }
void setBaseType(const Serialization::TypeID& baseType) { baseType_ = baseType; }
const char* derivedTypeName() const{ return derivedTypeName_.c_str(); }
void setDerivedType(const char* typeName, Serialization::IClassFactory* factory);
void setFactory(Serialization::IClassFactory* factory) { factory_ = factory; }
Serialization::IClassFactory* factory() const{ return factory_; }
bool onActivate(QPropertyTree* tree, bool force);
bool onMouseDown(QPropertyTree* tree, QPoint point, bool& changed);
bool onContextMenu(QMenu& root, QPropertyTree* tree);
bool isStatic() const{ return false; }
bool isPointer() const{ return true; }
int widgetSizeMin(const QPropertyTree* tree) const override;
wstring generateLabel() const;
string valueAsString() const;
const char* typeNameForFilter([[maybe_unused]] QPropertyTree* tree) const override { return baseType_.name(); }
void redraw(const PropertyDrawContext& context);
WidgetPlacement widgetPlacement() const{ return WIDGET_VALUE; }
void serializeValue(Serialization::IArchive& ar);
const void* searchHandle() const override { return searchHandle_; }
Serialization::TypeID typeId() const override { return pointerType_; }
protected:
Serialization::TypeID baseType_;
string derivedTypeName_;
string derivedLabel_;
// this member is available for instances deserialized from clipboard:
Serialization::IClassFactory* factory_;
const void* searchHandle_;
Serialization::TypeID pointerType_;
Color colorOverride_;
};
#endif // CRYINCLUDE_EDITORCOMMON_QPROPERTYTREE_PROPERTYROWPOINTER_H

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