Loading [MathJax]/jax/output/HTML-CSS/config.js
Radium Engine  1.5.29
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PortIn.hpp
1#pragma once
2
3#include <Dataflow/RaDataflow.hpp>
4
5#include <Core/Containers/VariableSet.hpp>
6#include <Core/Utils/Log.hpp>
7#include <Core/Utils/Observable.hpp>
8#include <Dataflow/Core/Port.hpp>
9
10#include <optional>
11
12namespace Ra {
13namespace Dataflow {
14namespace Core {
15
16class PortBaseOut;
17template <typename T>
18class PortOut;
19
20class RA_DATAFLOW_CORE_API PortBaseIn : public PortBase
21{
22 public:
26 PortBaseIn() = delete;
27 PortBaseIn( const PortBaseIn& ) = delete;
28 PortBaseIn& operator=( const PortBaseIn& ) = delete;
30
31 virtual bool accept( PortBaseOut* portOut ) const;
32 virtual bool connect( PortBaseOut* portOut ) = 0;
33 virtual bool disconnect() = 0;
34
35 virtual bool is_link_mandatory() const;
36 virtual bool is_linked() const = 0;
37 virtual bool has_default_value() const = 0;
38 virtual void insert( Ra::Core::VariableSet& ) = 0;
39 virtual PortBaseOut* link() = 0;
40
41 template <typename T>
42 PortOut<T>* link_as();
43
44 template <typename T>
45 void set_default_value( const T& value );
46
47 template <typename T>
48 T& data();
49
50 protected:
57 PortBaseIn( Node* node, const std::string& name, std::type_index type );
58};
59
69template <typename T>
70class PortIn : public PortBaseIn,
71 public Ra::Core::Utils::Observable<const std::string&, const PortIn<T>&, bool>
72{
73 public:
74 using DataType = T;
75
79 PortIn() = delete;
80 PortIn( const PortIn& ) = delete;
81 PortIn& operator=( const PortIn& ) = delete;
87 PortIn( Node* node, const std::string& name ) : PortBaseIn( node, name, typeid( T ) ) {
88 add_port_type<T>();
89 }
92 PortIn( Node* node, const std::string& name, const T& value ) :
93 PortBaseIn( node, name, typeid( T ) ), m_defaultValue { value } {
94 add_port_type<T>();
95 }
97
100 bool has_data() override;
101
109 T& data();
110
113 bool accept( PortBaseOut* portOut ) const override;
114 bool accept( PortOut<T>* portOut ) const;
115
116 bool connect( PortBaseOut* portOut ) override;
117 bool connect( PortOut<T>* portOut );
118
119 bool disconnect() override;
120
121 PortBaseOut* link() override { return m_from; }
123
124 void set_default_value( const T& value ) { m_defaultValue = value; }
125 T& default_value() { return *m_defaultValue; }
126 bool has_default_value() const override { return m_defaultValue.has_value(); }
127 void insert( Ra::Core::VariableSet& v ) override {
128 if ( has_default_value() )
129 v.setVariable( name(), std::reference_wrapper( *m_defaultValue ) );
130 }
131
132 bool is_linked() const override { return m_from != nullptr; }
133
134 template <typename B = T,
135 std::enable_if_t<std::is_constructible<nlohmann::json, B>::value, bool> = true>
136 void to_json_impl( nlohmann::json& data ) {
137 if ( has_default_value() ) { data["default_value"] = default_value(); }
138 }
139 template <typename B = T,
140 std::enable_if_t<!std::is_constructible<nlohmann::json, B>::value, bool> = true>
141 void to_json_impl( nlohmann::json& data ) {
142 if ( has_default_value() ) {
143 data["default_value"] =
144 std::string( "Default value not saved, missing json export for " ) +
145 Ra::Core::Utils::simplifiedDemangledType<T>();
146 }
147 }
148 template <typename B = T,
149 std::enable_if_t<std::is_assignable<nlohmann::json, B>::value, bool> = true>
150 void from_json_impl( const nlohmann::json& data ) {
151 using namespace Ra::Core::Utils;
152 if ( auto value_it = data.find( "default_value" ); value_it != data.end() ) {
153 set_default_value( ( *value_it ).template get<T>() );
154 }
155 }
156 template <typename B = T,
157 std::enable_if_t<!std::is_assignable<nlohmann::json, B>::value, int> = true>
158 void from_json_impl( const nlohmann::json& data ) {
159 if ( auto it = data.find( "name" ); it != data.end() ) { set_name( *it ); }
160 }
161 void to_json( nlohmann::json& data ) override {
162 PortBase::to_json( data );
163 to_json_impl( data );
164 }
165 void from_json( const nlohmann::json& data ) override {
166 PortBase::from_json( data );
167 from_json_impl( data );
168 }
169
170 private:
171 PortOut<T>* m_from = nullptr;
172 std::optional<T> m_defaultValue {};
173
174}; // class PortIn<T>
175
176template <typename Type>
177using PortInPtr = PortPtr<PortIn<Type>>;
178template <typename Type>
179using PortInRawPtr = typename PortInPtr<Type>::element_type*;
180
181using PortBaseInPtr = PortPtr<PortBaseIn>;
182using PortBaseInRawPtr = PortRawPtr<PortBaseIn>;
183
184template <typename T>
185PortOut<T>* PortBaseIn::link_as() {
186 return static_cast<PortIn<T>*>( this )->getLink();
187}
188
189template <typename T>
190void PortBaseIn::set_default_value( const T& value ) {
191 static_cast<PortIn<T>*>( this )->set_default_value( value );
192}
193
194template <typename T>
195T& PortBaseIn::data() {
196 return static_cast<PortIn<T>*>( this )->data();
197}
198
199template <typename T>
201 if ( is_linked() ) return m_from->data();
202 if ( m_defaultValue ) return *m_defaultValue;
203 CORE_ASSERT( false, "should not get here" );
204 using namespace Ra::Core::Utils;
205 LOG( logERROR ) << "graph is not valid";
206 return *m_defaultValue;
207}
208
209template <typename T>
210inline bool PortIn<T>::has_data() {
211 if ( is_linked() ) { return m_from->has_data(); }
212 return m_defaultValue.has_value();
213}
214
215template <typename T>
216bool PortIn<T>::accept( PortBaseOut* portOut ) const {
217 return !m_from && ( PortBaseIn::accept( portOut ) );
218}
219
220template <typename T>
221bool PortIn<T>::accept( PortOut<T>* ) const {
222 return !m_from;
223}
224
225template <typename T>
226bool PortIn<T>::connect( PortBaseOut* portOut ) {
227 if ( accept( portOut ) ) {
228 m_from = static_cast<PortOut<T>*>( portOut );
229 m_from->increase_link_count();
230 // notify after connect
231 this->notify( name(), *this, true );
232 }
233 return ( m_from );
234}
235
236template <typename T>
237bool PortIn<T>::connect( PortOut<T>* portOut ) {
238 if ( accept( portOut ) ) {
239 m_from = portOut;
240 m_from->increase_link_count();
241 // notify after connect
242 this->notify( name(), *this, true );
243 }
244 return ( m_from );
245}
246
247template <typename T>
248bool PortIn<T>::disconnect() {
249 if ( m_from ) {
250 // notify before disconnect
251 m_from->decrease_link_count();
252 this->notify( name(), *this, false );
253 m_from = nullptr;
254 return true;
255 }
256 return false;
257}
258
259} // namespace Core
260} // namespace Dataflow
261} // namespace Ra
Heterogeneous container storing "Variables", that maps a name (std::string) to a value (of any type T...
auto setVariable(const std::string &name, const T &value) -> std::pair< VariableHandle< T >, bool >
reset (or set if the variable does not exist yet) the value of the variable.
Base abstract class for all the nodes added and used by the node system.
Definition Node.hpp:40
const std::string & name() const
Gets the port's name.
Definition Port.hpp:52
Node * node() const
Gets a pointer to the node this port belongs to.
Definition Port.hpp:58
void set_name(const std::string &name)
Set's port name.
Definition Port.hpp:54
Input port accepting data of type T.
Definition PortOut.hpp:17
PortIn(Node *node, const std::string &name, const T &value)
Definition PortIn.hpp:92
T & data()
Gets the data pointed by the connected out port.
Definition PortIn.hpp:200
bool has_data() override
Definition PortIn.hpp:210
PortIn(Node *node, const std::string &name)
Definition PortIn.hpp:87
Forward PortOut classes used by getLink and reflect.
Definition PortOut.hpp:73
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4