添加项目文件。
This commit is contained in:
53
NodeEditorPro/include/nodes/Compiler.hpp
Normal file
53
NodeEditorPro/include/nodes/Compiler.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#if \
|
||||
defined (__MINGW32__) || \
|
||||
defined (__MINGW64__)
|
||||
# define NODE_EDITOR_COMPILER "MinGW"
|
||||
# define NODE_EDITOR_COMPILER_MINGW
|
||||
#elif \
|
||||
defined (__GNUC__)
|
||||
# define NODE_EDITOR_COMPILER "GNU"
|
||||
# define NODE_EDITOR_COMPILER_GNU
|
||||
# define NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR __GNUC__
|
||||
# define NODE_EDITOR_COMPILER_GNU_VERSION_MINOR __GNUC_MINOR__
|
||||
# define NODE_EDITOR_COMPILER_GNU_VERSION_PATCH __GNUC_PATCHLEVEL__
|
||||
#elif \
|
||||
defined (__clang__)
|
||||
# define NODE_EDITOR_COMPILER "Clang"
|
||||
# define NODE_EDITOR_COMPILER_CLANG
|
||||
#elif \
|
||||
defined (_MSC_VER)
|
||||
# define NODE_EDITOR_COMPILER "Microsoft Visual C++"
|
||||
# define NODE_EDITOR_COMPILER_MICROSOFT
|
||||
#elif \
|
||||
defined (__BORLANDC__)
|
||||
# define NODE_EDITOR_COMPILER "Borland C++ Builder"
|
||||
# define NODE_EDITOR_COMPILER_BORLAND
|
||||
#elif \
|
||||
defined (__CODEGEARC__)
|
||||
# define NODE_EDITOR_COMPILER "CodeGear C++ Builder"
|
||||
# define NODE_EDITOR_COMPILER_CODEGEAR
|
||||
#elif \
|
||||
defined (__INTEL_COMPILER) || \
|
||||
defined (__ICL)
|
||||
# define NODE_EDITOR_COMPILER "Intel C++"
|
||||
# define NODE_EDITOR_COMPILER_INTEL
|
||||
#elif \
|
||||
defined (__xlC__) || \
|
||||
defined (__IBMCPP__)
|
||||
# define NODE_EDITOR_COMPILER "IBM XL C++"
|
||||
# define NODE_EDITOR_COMPILER_IBM
|
||||
#elif \
|
||||
defined (__HP_aCC)
|
||||
# define NODE_EDITOR_COMPILER "HP aC++"
|
||||
# define NODE_EDITOR_COMPILER_HP
|
||||
#elif \
|
||||
defined (__WATCOMC__)
|
||||
# define NODE_EDITOR_COMPILER "Watcom C++"
|
||||
# define NODE_EDITOR_COMPILER_WATCOM
|
||||
#endif
|
||||
|
||||
#ifndef NODE_EDITOR_COMPILER
|
||||
# error "Current compiler is not supported."
|
||||
#endif
|
167
NodeEditorPro/include/nodes/Connection.hpp
Normal file
167
NodeEditorPro/include/nodes/Connection.hpp
Normal file
@ -0,0 +1,167 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include "PortType.hpp"
|
||||
#include "NodeData.hpp"
|
||||
|
||||
#include "Serializable.hpp"
|
||||
#include "ConnectionState.hpp"
|
||||
#include "ConnectionGeometry.hpp"
|
||||
#include "TypeConverter.hpp"
|
||||
#include "QUuidStdHash.hpp"
|
||||
#include "Export.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
class QPointF;
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Node;
|
||||
class NodeData;
|
||||
class ConnectionGraphicsObject;
|
||||
|
||||
/**
|
||||
* \brief 节点连接线
|
||||
*/
|
||||
class Connection
|
||||
: public QObject
|
||||
, public Serializable
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/// 新的连接对象会连接到目标节点,连接的端口应当有 端口类型,端口序号
|
||||
/// 连接对象的另一端应当是相反的端口。
|
||||
Connection(PortType portType,
|
||||
Node& node,
|
||||
PortIndex portIndex);
|
||||
|
||||
Connection(Node& nodeIn,
|
||||
PortIndex portIndexIn,
|
||||
Node& nodeOut,
|
||||
PortIndex portIndexOut,
|
||||
TypeConverter converter =
|
||||
TypeConverter{});
|
||||
|
||||
Connection(const Connection&) = delete;
|
||||
Connection operator=(const Connection&) = delete;
|
||||
|
||||
~Connection();
|
||||
|
||||
public:
|
||||
|
||||
QJsonObject
|
||||
save() const override;
|
||||
|
||||
public:
|
||||
|
||||
QUuid
|
||||
id() const;
|
||||
|
||||
/// Remembers the end being dragged.
|
||||
/// Invalidates Node address.
|
||||
/// Grabs mouse.
|
||||
void
|
||||
setRequiredPort(PortType portType);
|
||||
PortType
|
||||
requiredPort() const;
|
||||
|
||||
void
|
||||
setGraphicsObject(std::unique_ptr<ConnectionGraphicsObject>&& graphics);
|
||||
|
||||
/// Assigns a node to the required port.
|
||||
/// It is assumed that there is a required port, no extra checks
|
||||
void
|
||||
setNodeToPort(Node& node,
|
||||
PortType portType,
|
||||
PortIndex portIndex);
|
||||
|
||||
void
|
||||
removeFromNodes() const;
|
||||
|
||||
public:
|
||||
|
||||
ConnectionGraphicsObject&
|
||||
getConnectionGraphicsObject() const;
|
||||
|
||||
ConnectionState const&
|
||||
connectionState() const;
|
||||
ConnectionState&
|
||||
connectionState();
|
||||
|
||||
ConnectionGeometry&
|
||||
connectionGeometry();
|
||||
|
||||
ConnectionGeometry const&
|
||||
connectionGeometry() const;
|
||||
|
||||
Node*
|
||||
getNode(PortType portType) const;
|
||||
|
||||
Node*&
|
||||
getNode(PortType portType);
|
||||
|
||||
PortIndex
|
||||
getPortIndex(PortType portType) const;
|
||||
|
||||
void
|
||||
clearNode(PortType portType);
|
||||
|
||||
NodeDataType
|
||||
dataType(PortType portType) const;
|
||||
|
||||
void
|
||||
setTypeConverter(TypeConverter converter);
|
||||
|
||||
bool
|
||||
complete() const;
|
||||
|
||||
public: // data propagation
|
||||
|
||||
void
|
||||
propagateData(std::shared_ptr<NodeData> nodeData) const;
|
||||
|
||||
void
|
||||
propagateEmptyData() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
void
|
||||
connectionCompleted(Connection const&) const;
|
||||
|
||||
void
|
||||
connectionMadeIncomplete(Connection const&) const;
|
||||
|
||||
private:
|
||||
|
||||
QUuid _uid;
|
||||
|
||||
private:
|
||||
|
||||
Node* _outNode = nullptr;
|
||||
Node* _inNode = nullptr;
|
||||
|
||||
PortIndex _outPortIndex;
|
||||
PortIndex _inPortIndex;
|
||||
|
||||
private:
|
||||
|
||||
ConnectionState _connectionState;
|
||||
ConnectionGeometry _connectionGeometry;
|
||||
|
||||
std::unique_ptr<ConnectionGraphicsObject>_connectionGraphicsObject;
|
||||
|
||||
TypeConverter _converter;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
void
|
||||
updated(Connection& conn) const;
|
||||
};
|
||||
}
|
60
NodeEditorPro/include/nodes/ConnectionGeometry.hpp
Normal file
60
NodeEditorPro/include/nodes/ConnectionGeometry.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "PortType.hpp"
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtCore/QRectF>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class ConnectionGeometry
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectionGeometry();
|
||||
|
||||
public:
|
||||
|
||||
QPointF const&
|
||||
getEndPoint(PortType portType) const;
|
||||
|
||||
void
|
||||
setEndPoint(PortType portType, QPointF const& point);
|
||||
|
||||
void
|
||||
moveEndPoint(PortType portType, QPointF const& offset);
|
||||
|
||||
QRectF
|
||||
boundingRect() const;
|
||||
|
||||
std::pair<QPointF, QPointF>
|
||||
pointsC1C2() const;
|
||||
|
||||
QPointF
|
||||
source() const { return _out; }
|
||||
QPointF
|
||||
sink() const { return _in; }
|
||||
|
||||
double
|
||||
lineWidth() const { return _lineWidth; }
|
||||
|
||||
bool
|
||||
hovered() const { return _hovered; }
|
||||
void
|
||||
setHovered(bool hovered) { _hovered = hovered; }
|
||||
|
||||
private:
|
||||
// local object coordinates
|
||||
QPointF _in;
|
||||
QPointF _out;
|
||||
|
||||
//int _animationPhase;
|
||||
|
||||
double _lineWidth;
|
||||
|
||||
bool _hovered;
|
||||
};
|
||||
}
|
89
NodeEditorPro/include/nodes/ConnectionGraphicsObject.hpp
Normal file
89
NodeEditorPro/include/nodes/ConnectionGraphicsObject.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include <QtWidgets/QGraphicsObject>
|
||||
|
||||
class QGraphicsSceneMouseEvent;
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class FlowScene;
|
||||
class Connection;
|
||||
class ConnectionGeometry;
|
||||
class Node;
|
||||
|
||||
/// Graphic Object for connection. Adds itself to scene
|
||||
class ConnectionGraphicsObject
|
||||
: public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ConnectionGraphicsObject(FlowScene& scene,
|
||||
Connection& connection);
|
||||
|
||||
virtual
|
||||
~ConnectionGraphicsObject();
|
||||
|
||||
enum { Type = UserType + 2 };
|
||||
int
|
||||
type() const override { return Type; }
|
||||
|
||||
public:
|
||||
|
||||
Connection&
|
||||
connection();
|
||||
|
||||
QRectF
|
||||
boundingRect() const override;
|
||||
|
||||
QPainterPath
|
||||
shape() const override;
|
||||
|
||||
void
|
||||
setGeometryChanged();
|
||||
|
||||
/// Updates the position of both ends
|
||||
void
|
||||
move();
|
||||
|
||||
void
|
||||
lock(bool locked);
|
||||
|
||||
protected:
|
||||
|
||||
void
|
||||
paint(QPainter* painter,
|
||||
QStyleOptionGraphicsItem const* option,
|
||||
QWidget* widget = 0) override;
|
||||
|
||||
void
|
||||
mousePressEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
|
||||
|
||||
void
|
||||
hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
addGraphicsEffect();
|
||||
|
||||
private:
|
||||
|
||||
FlowScene& _scene;
|
||||
|
||||
Connection& _connection;
|
||||
};
|
||||
}
|
71
NodeEditorPro/include/nodes/ConnectionState.hpp
Normal file
71
NodeEditorPro/include/nodes/ConnectionState.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "PortType.hpp"
|
||||
|
||||
class QPointF;
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Node;
|
||||
|
||||
/// Stores currently draggind end.
|
||||
/// Remembers last hovered Node.
|
||||
class ConnectionState
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectionState(PortType port = PortType::None)
|
||||
: _requiredPort(port)
|
||||
{}
|
||||
|
||||
ConnectionState(const ConnectionState&) = delete;
|
||||
ConnectionState operator=(const ConnectionState&) = delete;
|
||||
|
||||
~ConnectionState();
|
||||
|
||||
public:
|
||||
|
||||
void setRequiredPort(PortType end)
|
||||
{
|
||||
_requiredPort = end;
|
||||
}
|
||||
|
||||
PortType requiredPort() const
|
||||
{
|
||||
return _requiredPort;
|
||||
}
|
||||
|
||||
bool requiresPort() const
|
||||
{
|
||||
return _requiredPort != PortType::None;
|
||||
}
|
||||
|
||||
void setNoRequiredPort()
|
||||
{
|
||||
_requiredPort = PortType::None;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void interactWithNode(Node* node);
|
||||
|
||||
void setLastHoveredNode(Node* node);
|
||||
|
||||
Node*
|
||||
lastHoveredNode() const
|
||||
{
|
||||
return _lastHoveredNode;
|
||||
}
|
||||
|
||||
void resetLastHoveredNode();
|
||||
|
||||
private:
|
||||
|
||||
PortType _requiredPort;
|
||||
|
||||
Node* _lastHoveredNode{ nullptr };
|
||||
};
|
||||
}
|
58
NodeEditorPro/include/nodes/ConnectionStyle.hpp
Normal file
58
NodeEditorPro/include/nodes/ConnectionStyle.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "Style.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class ConnectionStyle : public Style
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectionStyle();
|
||||
|
||||
ConnectionStyle(QString jsonText);
|
||||
|
||||
public:
|
||||
|
||||
static void setConnectionStyle(QString fileName);
|
||||
|
||||
private:
|
||||
|
||||
void loadJsonFile(QString fileName) override;
|
||||
|
||||
void saveJsonFile(QString fileName) override;
|
||||
|
||||
public:
|
||||
|
||||
QColor constructionColor() const;
|
||||
QColor normalColor() const;
|
||||
QColor normalColor(QString typeId) const;
|
||||
QColor selectedColor() const;
|
||||
QColor selectedHaloColor() const;
|
||||
QColor hoveredColor() const;
|
||||
|
||||
float lineWidth() const;
|
||||
float constructionLineWidth() const;
|
||||
float pointDiameter() const;
|
||||
|
||||
bool useDataDefinedColors() const;
|
||||
|
||||
public:
|
||||
|
||||
QColor ConstructionColor;
|
||||
QColor NormalColor;
|
||||
QColor SelectedColor;
|
||||
QColor SelectedHaloColor;
|
||||
QColor HoveredColor;
|
||||
|
||||
float LineWidth;
|
||||
float ConstructionLineWidth;
|
||||
float PointDiameter;
|
||||
|
||||
bool UseDataDefinedColors;
|
||||
};
|
||||
}
|
166
NodeEditorPro/include/nodes/DataModelRegistry.hpp
Normal file
166
NodeEditorPro/include/nodes/DataModelRegistry.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "NodeDataModel.hpp"
|
||||
#include "TypeConverter.hpp"
|
||||
#include "Export.hpp"
|
||||
#include "QStringStdHash.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
/// Class uses map for storing models (name, model)
|
||||
class DataModelRegistry
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using RegistryItemPtr = std::unique_ptr<NodeDataModel>;
|
||||
using RegistryItemCreator = std::function<RegistryItemPtr()>;
|
||||
using RegisteredModelCreatorsMap = std::unordered_map<QString, RegistryItemCreator>;
|
||||
using RegisteredModelsCategoryMap = std::unordered_map<QString, QString>;
|
||||
using CategoriesSet = std::set<QString>;
|
||||
|
||||
using RegisteredTypeConvertersMap = std::unordered_map<
|
||||
TypeConverterId, TypeConverter, TypeConverterIdHash>;
|
||||
|
||||
DataModelRegistry() = default;
|
||||
~DataModelRegistry() = default;
|
||||
|
||||
DataModelRegistry(DataModelRegistry const&) = delete;
|
||||
DataModelRegistry(DataModelRegistry&&) = default;
|
||||
|
||||
DataModelRegistry& operator=(DataModelRegistry const&) = delete;
|
||||
DataModelRegistry& operator=(DataModelRegistry&&) = default;
|
||||
|
||||
public:
|
||||
|
||||
template<typename ModelType>
|
||||
void registerModel(RegistryItemCreator creator,
|
||||
QString const& category = u8"默认节点")
|
||||
{
|
||||
const QString name = computeName<ModelType>(HasStaticMethodName<ModelType>{}, creator);
|
||||
if (!_registeredItemCreators.count(name))
|
||||
{
|
||||
_registeredItemCreators[name] = std::move(creator);
|
||||
_categories.insert(category);
|
||||
_registeredModelsCategory[name] = category;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ModelType>
|
||||
void registerModel(QString const& category = u8"默认节点")
|
||||
{
|
||||
RegistryItemCreator creator = []() { return std::make_unique<ModelType>(); };
|
||||
registerModel<ModelType>(std::move(creator), category);
|
||||
}
|
||||
|
||||
template<typename ModelType>
|
||||
void registerModel(QString const& category,
|
||||
RegistryItemCreator creator)
|
||||
{
|
||||
registerModel<ModelType>(std::move(creator), category);
|
||||
}
|
||||
|
||||
template <typename ModelCreator>
|
||||
void registerModel(ModelCreator&& creator, QString const& category = u8"默认节点")
|
||||
{
|
||||
using ModelType = compute_model_type_t<decltype(creator())>;
|
||||
registerModel<ModelType>(std::forward<ModelCreator>(creator), category);
|
||||
}
|
||||
|
||||
template <typename ModelCreator>
|
||||
void registerModel(QString const& category, ModelCreator&& creator)
|
||||
{
|
||||
registerModel(std::forward<ModelCreator>(creator), category);
|
||||
}
|
||||
|
||||
void registerTypeConverter(TypeConverterId const& id,
|
||||
TypeConverter typeConverter)
|
||||
{
|
||||
_registeredTypeConverters[id] = std::move(typeConverter);
|
||||
}
|
||||
|
||||
std::unique_ptr<NodeDataModel>create(QString const& modelName);
|
||||
|
||||
RegisteredModelCreatorsMap const& registeredModelCreators() const;
|
||||
|
||||
RegisteredModelsCategoryMap const& registeredModelsCategoryAssociation() const;
|
||||
|
||||
CategoriesSet const& categories() const;
|
||||
|
||||
TypeConverter getTypeConverter(NodeDataType const& d1,
|
||||
NodeDataType const& d2) const;
|
||||
|
||||
private:
|
||||
|
||||
RegisteredModelsCategoryMap _registeredModelsCategory;
|
||||
|
||||
CategoriesSet _categories;
|
||||
|
||||
RegisteredModelCreatorsMap _registeredItemCreators;
|
||||
|
||||
RegisteredTypeConvertersMap _registeredTypeConverters;
|
||||
|
||||
private:
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasStaticMethodName
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct HasStaticMethodName<T,
|
||||
typename std::enable_if<std::is_same<decltype(T::Name()), QString>::value>::type>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
template <typename ModelType>
|
||||
static QString
|
||||
computeName(std::true_type, RegistryItemCreator const&)
|
||||
{
|
||||
return ModelType::Name();
|
||||
}
|
||||
|
||||
template <typename ModelType>
|
||||
static QString
|
||||
computeName(std::false_type, RegistryItemCreator const& creator)
|
||||
{
|
||||
return creator()->name();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapUniquePtr
|
||||
{
|
||||
// Assert always fires, but the compiler doesn't know this:
|
||||
static_assert(!std::is_same<T, T>::value,
|
||||
"The ModelCreator must return a std::unique_ptr<T>, where T "
|
||||
"inherits from NodeDataModel");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnwrapUniquePtr<std::unique_ptr<T>>
|
||||
{
|
||||
static_assert(std::is_base_of<NodeDataModel, T>::value,
|
||||
"The ModelCreator must return a std::unique_ptr<T>, where T "
|
||||
"inherits from NodeDataModel");
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename CreatorResult>
|
||||
using compute_model_type_t = typename UnwrapUniquePtr<CreatorResult>::type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
51
NodeEditorPro/include/nodes/Export.hpp
Normal file
51
NodeEditorPro/include/nodes/Export.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "Compiler.hpp"
|
||||
#include "OperatingSystem.hpp"
|
||||
|
||||
#ifdef NODE_EDITOR_PLATFORM_WINDOWS
|
||||
# define NODE_EDITOR_EXPORT __declspec(dllexport)
|
||||
# define NODE_EDITOR_IMPORT __declspec(dllimport)
|
||||
# define NODE_EDITOR_LOCAL
|
||||
#elif \
|
||||
NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR >= 4 || \
|
||||
defined (NODE_EDITOR_COMPILER_CLANG)
|
||||
# define NODE_EDITOR_EXPORT __attribute__((visibility("default")))
|
||||
# define NODE_EDITOR_IMPORT __attribute__((visibility("default")))
|
||||
# define NODE_EDITOR_LOCAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
# define NODE_EDITOR_EXPORT
|
||||
# define NODE_EDITOR_IMPORT
|
||||
# define NODE_EDITOR_LOCAL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define NODE_EDITOR_DEMANGLED extern "C"
|
||||
#else
|
||||
# define NODE_EDITOR_DEMANGLED
|
||||
#endif
|
||||
|
||||
|
||||
//#if defined (NODE_EDITOR_SHARED) && !defined (NODE_EDITOR_STATIC)
|
||||
//# ifdef NODE_EDITOR_EXPORTS
|
||||
//# define NODE_EDITOR_EXPORT
|
||||
//# else
|
||||
//# define NODE_EDITOR_IMPORT
|
||||
//# endif
|
||||
//# define NODE_EDITOR_PRIVATE NODE_EDITOR_LOCAL
|
||||
//#elif !defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC)
|
||||
//# define
|
||||
//# define NODE_EDITOR_PRIVATE
|
||||
//#elif defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC)
|
||||
//# ifdef NODE_EDITOR_EXPORTS
|
||||
//# error "Cannot build as shared and static simultaneously."
|
||||
//# else
|
||||
//# error "Cannot link against shared and static simultaneously."
|
||||
//# endif
|
||||
//#else
|
||||
//# ifdef NODE_EDITOR_EXPORTS
|
||||
//# error "Choose whether to build as shared or static."
|
||||
//# else
|
||||
//# error "Choose whether to link against shared or static."
|
||||
//# endif
|
||||
//#endif
|
168
NodeEditorPro/include/nodes/FlowScene.hpp
Normal file
168
NodeEditorPro/include/nodes/FlowScene.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtWidgets/QGraphicsScene>
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
|
||||
#include "QUuidStdHash.hpp"
|
||||
#include "Export.hpp"
|
||||
#include "DataModelRegistry.hpp"
|
||||
#include "TypeConverter.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class NodeDataModel;
|
||||
class FlowItemInterface;
|
||||
class Node;
|
||||
class NodeGraphicsObject;
|
||||
class Connection;
|
||||
class ConnectionGraphicsObject;
|
||||
class NodeStyle;
|
||||
|
||||
/// Scene holds connections and nodes.
|
||||
class FlowScene
|
||||
: public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
FlowScene(std::shared_ptr<DataModelRegistry> registry,
|
||||
QObject* parent = Q_NULLPTR);
|
||||
|
||||
FlowScene(QObject* parent = Q_NULLPTR);
|
||||
|
||||
~FlowScene();
|
||||
|
||||
public:
|
||||
|
||||
std::shared_ptr<Connection>
|
||||
createConnection(PortType connectedPort,
|
||||
Node& node,
|
||||
PortIndex portIndex);
|
||||
|
||||
std::shared_ptr<Connection>
|
||||
createConnection(Node& nodeIn,
|
||||
PortIndex portIndexIn,
|
||||
Node& nodeOut,
|
||||
PortIndex portIndexOut,
|
||||
TypeConverter const& converter = TypeConverter{});
|
||||
|
||||
std::shared_ptr<Connection> restoreConnection(QJsonObject const& connectionJson);
|
||||
|
||||
void deleteConnection(Connection const& connection);
|
||||
|
||||
Node& createNode(std::unique_ptr<NodeDataModel>&& dataModel);
|
||||
|
||||
Node& restoreNode(QJsonObject const& nodeJson);
|
||||
|
||||
void removeNode(Node& node);
|
||||
|
||||
DataModelRegistry& registry() const;
|
||||
|
||||
void setRegistry(std::shared_ptr<DataModelRegistry> registry);
|
||||
|
||||
void iterateOverNodes(std::function<void(Node*)> const& visitor);
|
||||
|
||||
void iterateOverNodeData(std::function<void(NodeDataModel*)> const& visitor);
|
||||
|
||||
void iterateOverNodeDataDependentOrder(std::function<void(NodeDataModel*)> const& visitor);
|
||||
|
||||
QPointF getNodePosition(Node const& node) const;
|
||||
|
||||
void setNodePosition(Node& node, QPointF const& pos) const;
|
||||
|
||||
QSizeF getNodeSize(Node const& node) const;
|
||||
|
||||
public:
|
||||
|
||||
std::unordered_map<QUuid, std::unique_ptr<Node> > const& nodes() const;
|
||||
|
||||
std::unordered_map<QUuid, std::shared_ptr<Connection> > const& connections() const;
|
||||
|
||||
std::vector<Node*> allNodes() const;
|
||||
|
||||
std::vector<Node*> selectedNodes() const;
|
||||
|
||||
public:
|
||||
|
||||
void clearScene();
|
||||
|
||||
void save() const;
|
||||
|
||||
void load();
|
||||
|
||||
QByteArray saveToMemory() const;
|
||||
|
||||
void loadFromMemory(const QByteArray& data);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Node has been created but not on the scene yet.
|
||||
* @see nodePlaced()
|
||||
*/
|
||||
void nodeCreated(Node& n);
|
||||
|
||||
/**
|
||||
* @brief Node has been added to the scene.
|
||||
* @details Connect to this signal if need a correct position of node.
|
||||
* @see nodeCreated()
|
||||
*/
|
||||
void nodePlaced(Node& n);
|
||||
|
||||
void nodeDeleted(Node& n);
|
||||
|
||||
void connectionCreated(Connection const& c);
|
||||
|
||||
void connectionDeleted(Connection const& c);
|
||||
|
||||
void nodeMoved(Node& n, const QPointF& newLocation);
|
||||
|
||||
void nodeDoubleClicked(Node& n);
|
||||
|
||||
void nodeClicked(Node& n);
|
||||
|
||||
void connectionHovered(Connection& c, QPoint screenPos);
|
||||
|
||||
void nodeHovered(Node& n, QPoint screenPos);
|
||||
|
||||
void connectionHoverLeft(Connection& c);
|
||||
|
||||
void nodeHoverLeft(Node& n);
|
||||
|
||||
void nodeContextMenu(Node& n, const QPointF& pos);
|
||||
|
||||
private:
|
||||
|
||||
using SharedConnection = std::shared_ptr<Connection>;
|
||||
using UniqueNode = std::unique_ptr<Node>;
|
||||
|
||||
// DO NOT reorder this member to go after the others.
|
||||
// This should outlive all the connections and nodes of
|
||||
// the graph, so that nodes can potentially have pointers into it,
|
||||
// which is why it comes first in the class.
|
||||
std::shared_ptr<DataModelRegistry> _registry;
|
||||
|
||||
std::unordered_map<QUuid, SharedConnection> _connections;
|
||||
std::unordered_map<QUuid, UniqueNode> _nodes;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void setupConnectionSignals(Connection const& c);
|
||||
|
||||
void sendConnectionCreatedToNodes(Connection const& c);
|
||||
void sendConnectionDeletedToNodes(Connection const& c);
|
||||
|
||||
};
|
||||
|
||||
Node*
|
||||
locateNodeAt(QPointF scenePoint, FlowScene& scene,
|
||||
QTransform const& viewTransform);
|
||||
}
|
72
NodeEditorPro/include/nodes/FlowView.hpp
Normal file
72
NodeEditorPro/include/nodes/FlowView.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QGraphicsView>
|
||||
#include <QDebug>
|
||||
|
||||
#include "Export.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class FlowScene;
|
||||
|
||||
class FlowView
|
||||
: public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
FlowView(QWidget* parent = Q_NULLPTR);
|
||||
FlowView(FlowScene* scene, QWidget* parent = Q_NULLPTR);
|
||||
|
||||
FlowView(const FlowView&) = delete;
|
||||
FlowView operator=(const FlowView&) = delete;
|
||||
|
||||
QAction* clearSelectionAction() const;
|
||||
|
||||
QAction* deleteSelectionAction() const;
|
||||
|
||||
void setScene(FlowScene* scene);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
void scaleUp();
|
||||
|
||||
void scaleDown();
|
||||
|
||||
void deleteSelectedNodes();
|
||||
|
||||
protected:
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent* event) override;
|
||||
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
void drawBackground(QPainter* painter, const QRectF& r) override;
|
||||
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
protected:
|
||||
|
||||
FlowScene* scene();
|
||||
|
||||
private:
|
||||
|
||||
QAction* _clearSelectionAction;
|
||||
QAction* _deleteSelectionAction;
|
||||
|
||||
QPointF _clickPos;
|
||||
|
||||
FlowScene* _scene;
|
||||
};
|
||||
}
|
35
NodeEditorPro/include/nodes/FlowViewStyle.hpp
Normal file
35
NodeEditorPro/include/nodes/FlowViewStyle.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "Style.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class FlowViewStyle : public Style
|
||||
{
|
||||
public:
|
||||
|
||||
FlowViewStyle();
|
||||
|
||||
FlowViewStyle(QString jsonText);
|
||||
|
||||
public:
|
||||
|
||||
static void setStyle(QString jsonText);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void loadJsonFile(QString fileName) override;
|
||||
void saveJsonFile(QString fileName) override;
|
||||
|
||||
public:
|
||||
|
||||
QColor BackgroundColor;
|
||||
QColor FineGridColor;
|
||||
QColor CoarseGridColor;
|
||||
};
|
||||
}
|
133
NodeEditorPro/include/nodes/Node.hpp
Normal file
133
NodeEditorPro/include/nodes/Node.hpp
Normal file
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include "PortType.hpp"
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "NodeState.hpp"
|
||||
#include "NodeGeometry.hpp"
|
||||
#include "NodeData.hpp"
|
||||
#include "NodeGraphicsObject.hpp"
|
||||
#include "ConnectionGraphicsObject.hpp"
|
||||
#include "Serializable.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Connection;
|
||||
class ConnectionState;
|
||||
class NodeGraphicsObject;
|
||||
class NodeDataModel;
|
||||
|
||||
class Node
|
||||
: public QObject
|
||||
, public Serializable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/// NodeDataModel should be an rvalue and is moved into the Node
|
||||
Node(std::unique_ptr<NodeDataModel>&& dataModel);
|
||||
|
||||
virtual
|
||||
~Node();
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief Json序列化
|
||||
* \return json object
|
||||
*/
|
||||
QJsonObject
|
||||
save() const override;
|
||||
/**
|
||||
* \brief Json反序列化
|
||||
* \param json json
|
||||
*/
|
||||
void
|
||||
restore(QJsonObject const& json) override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief 节点的QUuid
|
||||
* \return uid
|
||||
*/
|
||||
QUuid
|
||||
id() const;
|
||||
|
||||
void reactToPossibleConnection(PortType,
|
||||
NodeDataType const&,
|
||||
QPointF const& scenePoint);
|
||||
|
||||
void
|
||||
resetReactionToConnection();
|
||||
|
||||
public:
|
||||
|
||||
NodeGraphicsObject const&
|
||||
nodeGraphicsObject() const;
|
||||
|
||||
NodeGraphicsObject&
|
||||
nodeGraphicsObject();
|
||||
|
||||
void
|
||||
setGraphicsObject(std::unique_ptr<NodeGraphicsObject>&& graphics);
|
||||
|
||||
NodeGeometry&
|
||||
nodeGeometry();
|
||||
|
||||
NodeGeometry const&
|
||||
nodeGeometry() const;
|
||||
|
||||
NodeState const&
|
||||
nodeState() const;
|
||||
|
||||
NodeState&
|
||||
nodeState();
|
||||
|
||||
NodeDataModel*
|
||||
nodeDataModel() const;
|
||||
|
||||
public Q_SLOTS: // data propagation
|
||||
|
||||
/// Propagates incoming data to the underlying model.
|
||||
void
|
||||
propagateData(std::shared_ptr<NodeData> nodeData,
|
||||
PortIndex inPortIndex,
|
||||
const QUuid& connectionId) const;
|
||||
|
||||
/// Fetches data from model's OUT #index port
|
||||
/// and propagates it to the connection
|
||||
void
|
||||
onDataUpdated(PortIndex index);
|
||||
|
||||
/// Propagates empty data to the attached connection.
|
||||
void
|
||||
onDataInvalidated(PortIndex index);
|
||||
|
||||
/// update the graphic part if the size of the embeddedwidget changes
|
||||
void
|
||||
onNodeSizeUpdated();
|
||||
|
||||
private:
|
||||
|
||||
// addressing
|
||||
QUuid _uid;
|
||||
|
||||
// data
|
||||
std::unique_ptr<NodeDataModel> _nodeDataModel;
|
||||
|
||||
NodeState _nodeState;
|
||||
|
||||
// painting
|
||||
NodeGeometry _nodeGeometry;
|
||||
|
||||
std::unique_ptr<NodeGraphicsObject> _nodeGraphicsObject;
|
||||
};
|
||||
}
|
52
NodeEditorPro/include/nodes/NodeData.hpp
Normal file
52
NodeEditorPro/include/nodes/NodeData.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include "Export.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
struct NodeDataType
|
||||
{
|
||||
QString id;
|
||||
/**
|
||||
* \brief 用于比较的名称
|
||||
*/
|
||||
QString name;
|
||||
|
||||
friend bool operator<(QtNodes::NodeDataType const& d1,
|
||||
QtNodes::NodeDataType const& d2)
|
||||
{
|
||||
return d1.id < d2.id;
|
||||
}
|
||||
|
||||
friend bool operator==(const QtNodes::NodeDataType& d1,
|
||||
const QtNodes::NodeDataType& d2) noexcept
|
||||
{
|
||||
return d1.id == d2.id;
|
||||
}
|
||||
};
|
||||
|
||||
/// Class represents data transferred between nodes.
|
||||
/// @param type is used for comparing the types
|
||||
/// The actual data is stored in subtypes
|
||||
class NodeData
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~NodeData() = default;
|
||||
|
||||
virtual bool sameType(NodeData const& nodeData) const
|
||||
{
|
||||
return (this->type().id == nodeData.type().id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief 节点标签
|
||||
* \return 标签名字
|
||||
*/
|
||||
virtual NodeDataType type() const = 0;
|
||||
|
||||
};
|
||||
}
|
206
NodeEditorPro/include/nodes/NodeDataModel.hpp
Normal file
206
NodeEditorPro/include/nodes/NodeDataModel.hpp
Normal file
@ -0,0 +1,206 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
#include "PortType.hpp"
|
||||
#include "NodeData.hpp"
|
||||
#include "Serializable.hpp"
|
||||
#include "NodeGeometry.hpp"
|
||||
#include "NodeStyle.hpp"
|
||||
#include "NodePainterDelegate.hpp"
|
||||
#include "Export.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
enum class NodeValidationState
|
||||
{
|
||||
Valid,
|
||||
Warning,
|
||||
Error
|
||||
};
|
||||
|
||||
class Connection;
|
||||
|
||||
class StyleCollection;
|
||||
|
||||
class NodeDataModel
|
||||
: public QObject,
|
||||
//public QThread,
|
||||
public Serializable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
NodeDataModel();
|
||||
|
||||
virtual
|
||||
~NodeDataModel() = default;
|
||||
|
||||
/// Caption is used in GUI
|
||||
virtual QString
|
||||
caption() const = 0;
|
||||
|
||||
/// It is possible to hide caption in GUI
|
||||
virtual bool
|
||||
captionVisible() const { return true; }
|
||||
|
||||
/// Port caption is used in GUI to label individual ports
|
||||
virtual QString
|
||||
portCaption(PortType, PortIndex) const { return QString(); }
|
||||
|
||||
/// It is possible to hide port caption in GUI
|
||||
virtual bool
|
||||
portCaptionVisible(PortType, PortIndex) const { return false; }
|
||||
|
||||
/// Name makes this model unique
|
||||
virtual QString
|
||||
name() const = 0;
|
||||
|
||||
public:
|
||||
|
||||
QJsonObject
|
||||
save() const override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief 定义该节点有几个输入输出端口
|
||||
* \param portType 查询的端口类型
|
||||
* \return 返回查询类型的端口个数
|
||||
*/
|
||||
virtual
|
||||
unsigned int nPorts(PortType portType) const = 0;
|
||||
|
||||
virtual
|
||||
NodeDataType dataType(PortType portType, PortIndex portIndex) const = 0;
|
||||
|
||||
public:
|
||||
|
||||
enum class ConnectionPolicy
|
||||
{
|
||||
One,
|
||||
Many,
|
||||
};
|
||||
|
||||
virtual
|
||||
ConnectionPolicy
|
||||
portOutConnectionPolicy(PortIndex) const
|
||||
{
|
||||
return ConnectionPolicy::Many;
|
||||
}
|
||||
|
||||
virtual
|
||||
ConnectionPolicy
|
||||
portInConnectionPolicy(PortIndex) const
|
||||
{
|
||||
return ConnectionPolicy::One;
|
||||
}
|
||||
|
||||
NodeStyle const&
|
||||
nodeStyle() const;
|
||||
|
||||
void
|
||||
setNodeStyle(NodeStyle const& style);
|
||||
|
||||
public:
|
||||
|
||||
/// Triggers the algorithm
|
||||
virtual
|
||||
void
|
||||
setInData(std::shared_ptr<NodeData> nodeData,
|
||||
PortIndex port) = 0;
|
||||
|
||||
// Use this if portInConnectionPolicy returns ConnectionPolicy::Many
|
||||
virtual
|
||||
void
|
||||
setInData(std::shared_ptr<NodeData> nodeData,
|
||||
PortIndex port,
|
||||
const QUuid& connectionId)
|
||||
{
|
||||
Q_UNUSED(connectionId);
|
||||
setInData(nodeData, port);
|
||||
}
|
||||
|
||||
virtual
|
||||
std::shared_ptr<NodeData>
|
||||
outData(PortIndex port) = 0;
|
||||
|
||||
/**
|
||||
* It is recommented to preform a lazy initialization for the
|
||||
* embedded widget and create it inside this function, not in the
|
||||
* constructor of the current model.
|
||||
*
|
||||
* Our Model Registry is able to shortly instantiate models in order
|
||||
* to call the non-static `Model::name()`. If the embedded widget is
|
||||
* allocated in the constructor but not actually embedded into some
|
||||
* QGraphicsProxyWidget, we'll gonna have a dangling pointer.
|
||||
*/
|
||||
virtual
|
||||
QWidget*
|
||||
embeddedWidget() = 0;
|
||||
|
||||
virtual
|
||||
bool
|
||||
resizable() const { return false; }
|
||||
|
||||
virtual
|
||||
NodeValidationState
|
||||
validationState() const { return NodeValidationState::Valid; }
|
||||
|
||||
virtual
|
||||
QString
|
||||
validationMessage() const { return QString(""); }
|
||||
|
||||
virtual
|
||||
NodePainterDelegate* painterDelegate() const { return nullptr; }
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
virtual void
|
||||
inputConnectionCreated(Connection const&)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
inputConnectionDeleted(Connection const&)
|
||||
{
|
||||
//qDebug() << "inputConnectionDeleted";
|
||||
//emit sigInputConnectionDeleted();
|
||||
}
|
||||
|
||||
virtual void
|
||||
outputConnectionCreated(Connection const&)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
outputConnectionDeleted(Connection const&)
|
||||
{
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/// Triggers the updates in the nodes downstream.
|
||||
void dataUpdated(PortIndex index);
|
||||
|
||||
/// Triggers the propagation of the empty data downstream.
|
||||
void dataInvalidated(PortIndex index);
|
||||
|
||||
void computingStarted();
|
||||
|
||||
void computingFinished();
|
||||
|
||||
void embeddedWidgetSizeUpdated();
|
||||
|
||||
void sigInputConnectionDeleted();//输入连接移出信号
|
||||
|
||||
private:
|
||||
|
||||
NodeStyle _nodeStyle;
|
||||
};
|
||||
}
|
166
NodeEditorPro/include/nodes/NodeGeometry.hpp
Normal file
166
NodeEditorPro/include/nodes/NodeGeometry.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QRectF>
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtGui/QTransform>
|
||||
#include <QtGui/QFontMetrics>
|
||||
|
||||
#include "PortType.hpp"
|
||||
#include "Export.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class NodeState;
|
||||
class NodeDataModel;
|
||||
class Node;
|
||||
|
||||
class NodeGeometry
|
||||
{
|
||||
public:
|
||||
|
||||
NodeGeometry(std::unique_ptr<NodeDataModel> const& dataModel);
|
||||
|
||||
public:
|
||||
unsigned int
|
||||
height() const { return _height; }
|
||||
|
||||
void
|
||||
setHeight(unsigned int h) { _height = h; }
|
||||
|
||||
unsigned int
|
||||
width() const { return _width; }
|
||||
|
||||
void
|
||||
setWidth(unsigned int w) { _width = w; }
|
||||
|
||||
unsigned int
|
||||
entryHeight() const { return _entryHeight; }
|
||||
void
|
||||
setEntryHeight(unsigned int h) { _entryHeight = h; }
|
||||
|
||||
unsigned int
|
||||
entryWidth() const { return _entryWidth; }
|
||||
|
||||
void
|
||||
setEntryWidth(unsigned int w) { _entryWidth = w; }
|
||||
|
||||
unsigned int
|
||||
spacing() const { return _spacing; }
|
||||
|
||||
void
|
||||
setSpacing(unsigned int s) { _spacing = s; }
|
||||
|
||||
bool
|
||||
hovered() const { return _hovered; }
|
||||
|
||||
void
|
||||
setHovered(unsigned int h) { _hovered = h; }
|
||||
|
||||
unsigned int
|
||||
nSources() const;
|
||||
|
||||
unsigned int
|
||||
nSinks() const;
|
||||
|
||||
QPointF const&
|
||||
draggingPos() const
|
||||
{
|
||||
return _draggingPos;
|
||||
}
|
||||
|
||||
void
|
||||
setDraggingPosition(QPointF const& pos)
|
||||
{
|
||||
_draggingPos = pos;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
QRectF
|
||||
entryBoundingRect() const;
|
||||
|
||||
QRectF
|
||||
boundingRect() const;
|
||||
|
||||
/// Updates size unconditionally
|
||||
void
|
||||
recalculateSize() const;
|
||||
|
||||
/// Updates size if the QFontMetrics is changed
|
||||
void
|
||||
recalculateSize(QFont const& font) const;
|
||||
|
||||
// TODO removed default QTransform()
|
||||
QPointF
|
||||
portScenePosition(PortIndex index,
|
||||
PortType portType,
|
||||
QTransform const& t = QTransform()) const;
|
||||
|
||||
PortIndex
|
||||
checkHitScenePoint(PortType portType,
|
||||
QPointF point,
|
||||
QTransform const& t = QTransform()) const;
|
||||
|
||||
QRect
|
||||
resizeRect() const;
|
||||
|
||||
/// Returns the position of a widget on the Node surface
|
||||
QPointF
|
||||
widgetPosition() const;
|
||||
|
||||
/// Returns the maximum height a widget can be without causing the node to grow.
|
||||
int
|
||||
equivalentWidgetHeight() const;
|
||||
|
||||
unsigned int
|
||||
validationHeight() const;
|
||||
|
||||
unsigned int
|
||||
validationWidth() const;
|
||||
|
||||
static
|
||||
QPointF
|
||||
calculateNodePositionBetweenNodePorts(PortIndex targetPortIndex, PortType targetPort, Node* targetNode,
|
||||
PortIndex sourcePortIndex, PortType sourcePort, Node* sourceNode,
|
||||
Node& newNode);
|
||||
private:
|
||||
|
||||
unsigned int
|
||||
captionHeight() const;
|
||||
|
||||
unsigned int
|
||||
captionWidth() const;
|
||||
|
||||
unsigned int
|
||||
portWidth(PortType portType) const;
|
||||
|
||||
private:
|
||||
|
||||
// some variables are mutable because
|
||||
// we need to change drawing metrics
|
||||
// corresponding to fontMetrics
|
||||
// but this doesn't change constness of Node
|
||||
|
||||
mutable unsigned int _width;
|
||||
mutable unsigned int _height;
|
||||
unsigned int _entryWidth;
|
||||
mutable unsigned int _inputPortWidth;
|
||||
mutable unsigned int _outputPortWidth;
|
||||
mutable unsigned int _entryHeight;
|
||||
unsigned int _spacing;
|
||||
|
||||
bool _hovered;
|
||||
|
||||
unsigned int _nSources;
|
||||
unsigned int _nSinks;
|
||||
|
||||
QPointF _draggingPos;
|
||||
|
||||
std::unique_ptr<NodeDataModel> const& _dataModel;
|
||||
|
||||
mutable QFontMetrics _fontMetrics;
|
||||
mutable QFontMetrics _boldFontMetrics;
|
||||
};
|
||||
}
|
106
NodeEditorPro/include/nodes/NodeGraphicsObject.hpp
Normal file
106
NodeEditorPro/include/nodes/NodeGraphicsObject.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtWidgets/QGraphicsObject>
|
||||
|
||||
#include "Connection.hpp"
|
||||
|
||||
#include "NodeGeometry.hpp"
|
||||
#include "NodeState.hpp"
|
||||
|
||||
class QGraphicsProxyWidget;
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class FlowScene;
|
||||
class FlowItemEntry;
|
||||
|
||||
/// Class reacts on GUI events, mouse clicks and
|
||||
/// forwards painting operation.
|
||||
class NodeGraphicsObject : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NodeGraphicsObject(FlowScene& scene,
|
||||
Node& node);
|
||||
|
||||
virtual
|
||||
~NodeGraphicsObject();
|
||||
|
||||
Node&
|
||||
node();
|
||||
|
||||
Node const&
|
||||
node() const;
|
||||
|
||||
QRectF
|
||||
boundingRect() const override;
|
||||
|
||||
void
|
||||
setGeometryChanged();
|
||||
|
||||
/// Visits all attached connections and corrects
|
||||
/// their corresponding end points.
|
||||
void
|
||||
moveConnections() const;
|
||||
|
||||
enum { Type = UserType + 1 };
|
||||
|
||||
int
|
||||
type() const override { return Type; }
|
||||
|
||||
void
|
||||
lock(bool locked);
|
||||
|
||||
protected:
|
||||
void
|
||||
paint(QPainter* painter,
|
||||
QStyleOptionGraphicsItem const* option,
|
||||
QWidget* widget = 0) override;
|
||||
|
||||
QVariant
|
||||
itemChange(GraphicsItemChange change, const QVariant& value) override;
|
||||
|
||||
void
|
||||
mousePressEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
|
||||
|
||||
void
|
||||
hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
|
||||
|
||||
void
|
||||
hoverMoveEvent(QGraphicsSceneHoverEvent*) override;
|
||||
|
||||
void
|
||||
mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) override;
|
||||
|
||||
void
|
||||
contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
embedQWidget();
|
||||
|
||||
private:
|
||||
|
||||
FlowScene& _scene;
|
||||
|
||||
Node& _node;
|
||||
|
||||
bool _locked;
|
||||
|
||||
// either nullptr or owned by parent QGraphicsItem
|
||||
QGraphicsProxyWidget* _proxyWidget;
|
||||
};
|
||||
}
|
25
NodeEditorPro/include/nodes/NodePainterDelegate.hpp
Normal file
25
NodeEditorPro/include/nodes/NodePainterDelegate.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "NodeGeometry.hpp"
|
||||
#include "NodeDataModel.hpp"
|
||||
#include "Export.hpp"
|
||||
|
||||
namespace QtNodes {
|
||||
|
||||
/// Class to allow for custom painting
|
||||
class NodePainterDelegate
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual
|
||||
~NodePainterDelegate() = default;
|
||||
|
||||
virtual void
|
||||
paint(QPainter* painter,
|
||||
NodeGeometry const& geom,
|
||||
NodeDataModel const* model) = 0;
|
||||
};
|
||||
}
|
97
NodeEditorPro/include/nodes/NodeState.hpp
Normal file
97
NodeEditorPro/include/nodes/NodeState.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "Export.hpp"
|
||||
|
||||
#include "PortType.hpp"
|
||||
#include "NodeData.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Connection;
|
||||
class NodeDataModel;
|
||||
|
||||
/// Contains vectors of connected input and output connections.
|
||||
/// Stores bool for reacting on hovering connections
|
||||
class NodeState
|
||||
{
|
||||
public:
|
||||
enum ReactToConnectionState
|
||||
{
|
||||
REACTING,
|
||||
NOT_REACTING
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
NodeState(std::unique_ptr<NodeDataModel> const& model);
|
||||
|
||||
public:
|
||||
|
||||
using ConnectionPtrSet =
|
||||
std::unordered_map<QUuid, Connection*>;
|
||||
|
||||
/// Returns vector of connections ID.
|
||||
/// Some of them can be empty (null)
|
||||
std::vector<ConnectionPtrSet> const&
|
||||
getEntries(PortType) const;
|
||||
|
||||
std::vector<ConnectionPtrSet>&
|
||||
getEntries(PortType);
|
||||
|
||||
ConnectionPtrSet
|
||||
connections(PortType portType, PortIndex portIndex) const;
|
||||
|
||||
void
|
||||
setConnection(PortType portType,
|
||||
PortIndex portIndex,
|
||||
Connection& connection);
|
||||
|
||||
void
|
||||
eraseConnection(PortType portType,
|
||||
PortIndex portIndex,
|
||||
QUuid id);
|
||||
|
||||
ReactToConnectionState
|
||||
reaction() const;
|
||||
|
||||
PortType
|
||||
reactingPortType() const;
|
||||
|
||||
NodeDataType
|
||||
reactingDataType() const;
|
||||
|
||||
void
|
||||
setReaction(ReactToConnectionState reaction,
|
||||
PortType reactingPortType = PortType::None,
|
||||
|
||||
NodeDataType reactingDataType =
|
||||
NodeDataType());
|
||||
|
||||
bool
|
||||
isReacting() const;
|
||||
|
||||
void
|
||||
setResizing(bool resizing);
|
||||
|
||||
bool
|
||||
resizing() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<ConnectionPtrSet> _inConnections;
|
||||
std::vector<ConnectionPtrSet> _outConnections;
|
||||
|
||||
ReactToConnectionState _reaction;
|
||||
PortType _reactingPortType;
|
||||
NodeDataType _reactingDataType;
|
||||
|
||||
bool _resizing;
|
||||
};
|
||||
}
|
55
NodeEditorPro/include/nodes/NodeStyle.hpp
Normal file
55
NodeEditorPro/include/nodes/NodeStyle.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include "Export.hpp"
|
||||
#include "Style.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class NodeStyle : public Style
|
||||
{
|
||||
public:
|
||||
|
||||
NodeStyle();
|
||||
|
||||
NodeStyle(QString jsonText);
|
||||
|
||||
public:
|
||||
|
||||
static void setNodeStyle(QString fileName);
|
||||
|
||||
private:
|
||||
|
||||
void loadJsonFile(QString fileName) override;
|
||||
void saveJsonFile(QString fileName) override;
|
||||
|
||||
public:
|
||||
|
||||
QColor NormalBoundaryColor;
|
||||
QColor SelectedBoundaryColor;
|
||||
QColor BackgroundColor;
|
||||
QColor TitleColor;
|
||||
QColor GradientColor0;
|
||||
QColor GradientColor1;
|
||||
QColor GradientColor2;
|
||||
QColor GradientColor3;
|
||||
QColor ShadowColor;
|
||||
QColor FontColor;
|
||||
QColor FontColorFaded;
|
||||
|
||||
QColor ConnectionPointColor;
|
||||
QColor FilledConnectionPointColor;
|
||||
|
||||
QColor WarningColor;
|
||||
QColor ErrorColor;
|
||||
|
||||
float PenWidth;
|
||||
float HoveredPenWidth;
|
||||
|
||||
float ConnectionPointDiameter;
|
||||
|
||||
float Opacity;
|
||||
};
|
||||
}
|
78
NodeEditorPro/include/nodes/OperatingSystem.hpp
Normal file
78
NodeEditorPro/include/nodes/OperatingSystem.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#if \
|
||||
defined (__CYGWIN__) || \
|
||||
defined (__CYGWIN32__)
|
||||
# define NODE_EDITOR_PLATFORM "Cygwin"
|
||||
# define NODE_EDITOR_PLATFORM_CYGWIN
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
# define NODE_EDITOR_PLATFORM_WINDOWS
|
||||
#elif \
|
||||
defined (_WIN16) || \
|
||||
defined (_WIN32) || \
|
||||
defined (_WIN64) || \
|
||||
defined (__WIN32__) || \
|
||||
defined (__TOS_WIN__) || \
|
||||
defined (__WINDOWS__)
|
||||
# define NODE_EDITOR_PLATFORM "Windows"
|
||||
# define NODE_EDITOR_PLATFORM_WINDOWS
|
||||
#elif \
|
||||
defined (macintosh) || \
|
||||
defined (Macintosh) || \
|
||||
defined (__TOS_MACOS__) || \
|
||||
(defined (__APPLE__) && defined (__MACH__))
|
||||
# define NODE_EDITOR_PLATFORM "Mac"
|
||||
# define NODE_EDITOR_PLATFORM_MAC
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (linux) || \
|
||||
defined (__linux) || \
|
||||
defined (__linux__) || \
|
||||
defined (__TOS_LINUX__)
|
||||
# define NODE_EDITOR_PLATFORM "Linux"
|
||||
# define NODE_EDITOR_PLATFORM_LINUX
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (__FreeBSD__) || \
|
||||
defined (__OpenBSD__) || \
|
||||
defined (__NetBSD__) || \
|
||||
defined (__bsdi__) || \
|
||||
defined (__DragonFly__)
|
||||
# define NODE_EDITOR_PLATFORM "BSD"
|
||||
# define NODE_EDITOR_PLATFORM_BSD
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (sun) || \
|
||||
defined (__sun)
|
||||
# define NODE_EDITOR_PLATFORM "Solaris"
|
||||
# define NODE_EDITOR_PLATFORM_SOLARIS
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (_AIX) || \
|
||||
defined (__TOS_AIX__)
|
||||
# define NODE_EDITOR_PLATFORM "AIX"
|
||||
# define NODE_EDITOR_PLATFORM_AIX
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (hpux) || \
|
||||
defined (_hpux) || \
|
||||
defined (__hpux)
|
||||
# define NODE_EDITOR_PLATFORM "HPUX"
|
||||
# define NODE_EDITOR_PLATFORM_HPUX
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (__QNX__)
|
||||
# define NODE_EDITOR_PLATFORM "QNX"
|
||||
# define NODE_EDITOR_PLATFORM_QNX
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#elif \
|
||||
defined (unix) || \
|
||||
defined (__unix) || \
|
||||
defined (__unix__)
|
||||
# define NODE_EDITOR_PLATFORM "Unix"
|
||||
# define NODE_EDITOR_PLATFORM_UNIX
|
||||
#endif
|
||||
|
||||
#ifndef NODE_EDITOR_PLATFORM
|
||||
# error "Current platform is not supported."
|
||||
#endif
|
67
NodeEditorPro/include/nodes/PortType.hpp
Normal file
67
NodeEditorPro/include/nodes/PortType.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
enum class PortType
|
||||
{
|
||||
None,
|
||||
In,
|
||||
Out
|
||||
};
|
||||
|
||||
static const int INVALID = -1;
|
||||
|
||||
using PortIndex = int;
|
||||
|
||||
struct Port
|
||||
{
|
||||
PortType type;
|
||||
|
||||
PortIndex index;
|
||||
|
||||
Port()
|
||||
: type(PortType::None)
|
||||
, index(INVALID)
|
||||
{}
|
||||
|
||||
Port(PortType t, PortIndex i)
|
||||
: type(t)
|
||||
, index(i)
|
||||
{}
|
||||
|
||||
bool
|
||||
indexIsValid() { return index != INVALID; }
|
||||
|
||||
bool
|
||||
portTypeIsValid() { return type != PortType::None; }
|
||||
};
|
||||
|
||||
//using PortAddress = std::pair<QUuid, PortIndex>;
|
||||
|
||||
inline
|
||||
PortType
|
||||
oppositePort(PortType port)
|
||||
{
|
||||
PortType result = PortType::None;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case PortType::In:
|
||||
result = PortType::Out;
|
||||
break;
|
||||
|
||||
case PortType::Out:
|
||||
result = PortType::In;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
27
NodeEditorPro/include/nodes/QStringStdHash.hpp
Normal file
27
NodeEditorPro/include/nodes/QStringStdHash.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
|
||||
|
||||
// As of 5.14 there is a specialization std::hash<QString>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<QString>
|
||||
{
|
||||
inline std::size_t
|
||||
operator()(QString const& s) const
|
||||
{
|
||||
return qHash(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
21
NodeEditorPro/include/nodes/QUuidStdHash.hpp
Normal file
21
NodeEditorPro/include/nodes/QUuidStdHash.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<QUuid>
|
||||
{
|
||||
inline
|
||||
std::size_t
|
||||
operator()(QUuid const& uid) const
|
||||
{
|
||||
return qHash(uid);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
22
NodeEditorPro/include/nodes/Serializable.hpp
Normal file
22
NodeEditorPro/include/nodes/Serializable.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Serializable
|
||||
{
|
||||
public:
|
||||
|
||||
virtual
|
||||
~Serializable() = default;
|
||||
|
||||
virtual
|
||||
QJsonObject
|
||||
save() const = 0;
|
||||
|
||||
virtual void
|
||||
restore(QJsonObject const& /*p*/) {}
|
||||
};
|
||||
}
|
23
NodeEditorPro/include/nodes/Style.hpp
Normal file
23
NodeEditorPro/include/nodes/Style.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class Style
|
||||
{
|
||||
public:
|
||||
|
||||
virtual
|
||||
~Style() = default;
|
||||
|
||||
private:
|
||||
|
||||
virtual void
|
||||
loadJsonFile(QString fileName) = 0;
|
||||
virtual void
|
||||
saveJsonFile(QString fileName) = 0;
|
||||
};
|
||||
|
||||
}
|
62
NodeEditorPro/include/nodes/StyleCollection.hpp
Normal file
62
NodeEditorPro/include/nodes/StyleCollection.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "NodeStyle.hpp"
|
||||
#include "ConnectionStyle.hpp"
|
||||
#include "FlowViewStyle.hpp"
|
||||
#include "Export.hpp"
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
class StyleCollection
|
||||
{
|
||||
public:
|
||||
|
||||
static
|
||||
NodeStyle const&
|
||||
nodeStyle();
|
||||
|
||||
static
|
||||
ConnectionStyle const&
|
||||
connectionStyle();
|
||||
|
||||
static
|
||||
FlowViewStyle const&
|
||||
flowViewStyle();
|
||||
|
||||
public:
|
||||
|
||||
static
|
||||
void
|
||||
setNodeStyle(NodeStyle);
|
||||
|
||||
static
|
||||
void
|
||||
setConnectionStyle(ConnectionStyle);
|
||||
|
||||
static
|
||||
void
|
||||
setFlowViewStyle(FlowViewStyle);
|
||||
|
||||
private:
|
||||
|
||||
StyleCollection() = default;
|
||||
|
||||
StyleCollection(StyleCollection const&) = delete;
|
||||
|
||||
StyleCollection&
|
||||
operator=(StyleCollection const&) = delete;
|
||||
|
||||
static
|
||||
StyleCollection&
|
||||
instance();
|
||||
|
||||
private:
|
||||
|
||||
NodeStyle _nodeStyle;
|
||||
|
||||
ConnectionStyle _connectionStyle;
|
||||
|
||||
FlowViewStyle _flowViewStyle;
|
||||
};
|
||||
}
|
30
NodeEditorPro/include/nodes/TypeConverter.hpp
Normal file
30
NodeEditorPro/include/nodes/TypeConverter.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "NodeData.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
|
||||
using SharedNodeData = std::shared_ptr<NodeData>;
|
||||
|
||||
// a function taking in NodeData and returning NodeData
|
||||
using TypeConverter =
|
||||
std::function<SharedNodeData(SharedNodeData)>;
|
||||
|
||||
// data-type-in, data-type-out
|
||||
using TypeConverterId =
|
||||
std::pair<NodeDataType, NodeDataType>;
|
||||
|
||||
struct TypeConverterIdHash
|
||||
{
|
||||
std::size_t operator()(const QtNodes::TypeConverterId& converter) const noexcept
|
||||
{
|
||||
return qHash(converter.first.id)
|
||||
^ qHash(converter.second.id);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
26
NodeEditorPro/include/nodes/memory.hpp
Normal file
26
NodeEditorPro/include/nodes/memory.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace QtNodes
|
||||
{
|
||||
namespace detail {
|
||||
#if (!defined(_MSC_VER) && (__cplusplus < 201300)) || \
|
||||
( defined(_MSC_VER) && (_MSC_VER < 1800))
|
||||
//_MSC_VER == 1800 is Visual Studio 2013, which is already somewhat C++14 compilant,
|
||||
// and it has make_unique in it's standard library implementation
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
#else
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args)
|
||||
{
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user