From bdac191dedd919ddae0f1aa27d3a3f0fb1f19904 Mon Sep 17 00:00:00 2001 From: Alex Link Date: Mon, 14 Oct 2024 10:40:15 +0200 Subject: [PATCH] [#104] - :sparkles: the final work for now --- wire/CMakeLists.txt | 3 + wire/slot/input_slot.h | 2 +- wire/slot/sheet.hpp | 8 +- wire/variable.hpp | 28 ++- wire/variables/trafo_variables.hpp | 183 ++++++++++++++ wire/variables/vector_variables.hpp | 356 ++++++++++++++++++++++++++++ 6 files changed, 576 insertions(+), 4 deletions(-) create mode 100644 wire/variables/trafo_variables.hpp create mode 100644 wire/variables/vector_variables.hpp diff --git a/wire/CMakeLists.txt b/wire/CMakeLists.txt index 468759d..841c41f 100644 --- a/wire/CMakeLists.txt +++ b/wire/CMakeLists.txt @@ -20,6 +20,9 @@ set( SOURCES ${SOURCES} "slot/output_slot.cpp" "slot/sheet.hpp" "slot/other_slot.hpp" + + "variables/vector_variables.hpp" + "variables/trafo_variables.hpp" ) motor_vs_src_dir( SOURCES ) diff --git a/wire/slot/input_slot.h b/wire/slot/input_slot.h index bf14a6a..5966c40 100644 --- a/wire/slot/input_slot.h +++ b/wire/slot/input_slot.h @@ -65,7 +65,7 @@ namespace motor virtual void_t disconnect( bool_t const propagate = true ) noexcept { if ( _output_slot == nullptr ) return ; - if ( propagate ) _output_slot->disconnect( this ) ; + if ( propagate ) _output_slot->disconnect( this, false ) ; motor::memory::release_ptr( motor::move( _output_slot ) ) ; //_value = T( 0 ) ; diff --git a/wire/slot/sheet.hpp b/wire/slot/sheet.hpp index 34bc97c..d0a516d 100644 --- a/wire/slot/sheet.hpp +++ b/wire/slot/sheet.hpp @@ -113,8 +113,12 @@ namespace motor bool_t connect( motor::string_in_t name, typename motor::wire::other_slot< T >::type_safe_mtr_t slot ) noexcept { auto * this_slot = this_t::borrow( name ) ; - if( this_slot == nullptr ) return false ; - return this_slot->connect( slot ) ; + if( this_slot == nullptr ) + { + motor::release( motor::move( slot ) ) ; + return false ; + } + return this_slot->connect( motor::move( slot ) ) ; } }; motor_typedefs( sheet< motor::wire::ioutput_slot >, outputs ) ; diff --git a/wire/variable.hpp b/wire/variable.hpp index 839613e..9e694e1 100644 --- a/wire/variable.hpp +++ b/wire/variable.hpp @@ -11,6 +11,12 @@ namespace motor { namespace wire { + enum sub_update_strategy + { + never, + always + }; + class any { motor_this_typedefs( any ) ; @@ -22,6 +28,9 @@ namespace motor motor::wire::iinput_slot_ptr_t _in = nullptr ; motor::wire::ioutput_slot_ptr_t _out = nullptr ; + // how to automatically update sub member variables + sub_update_strategy _strat = sub_update_strategy::never ; + public: struct member_info @@ -38,6 +47,9 @@ namespace motor any( char const * name, motor::wire::iinput_slot_ptr_t in_, motor::wire::ioutput_slot_ptr_t out_ ) noexcept : _name( name ), _in( in_ ), _out( out_ ) {} + any( char const * name, motor::wire::iinput_slot_ptr_t in_, motor::wire::ioutput_slot_ptr_t out_, sub_update_strategy const us ) noexcept : + _name( name ), _in( in_ ), _out( out_ ), _strat( us ) {} + any( this_cref_t ) = delete ; any( this_rref_t rhv ) noexcept : _name( motor::move( rhv._name ) ), _in( motor::move( rhv._in ) ), _out( motor::move( rhv._out ) ){ } @@ -63,10 +75,13 @@ namespace motor return ret ; } - public: + public: // virtual // return bool if anything changed. virtual bool_t update( void_t ) noexcept = 0 ; + virtual void_t update_strat_changed( motor::wire::sub_update_strategy const ) noexcept {} + + public: motor::wire::iinput_slot_mtr_safe_t get_is( void_t ) noexcept { @@ -78,6 +93,17 @@ namespace motor return motor::share( _out ) ; } + motor::wire::sub_update_strategy get_update_strategy( void_t ) const noexcept + { + return _strat ; + } + + void_t set_update_strategy( motor::wire::sub_update_strategy const s ) noexcept + { + _strat = s ; + this->update_strat_changed( s ) ; + } + protected: template< typename T > diff --git a/wire/variables/trafo_variables.hpp b/wire/variables/trafo_variables.hpp new file mode 100644 index 0000000..24fffc3 --- /dev/null +++ b/wire/variables/trafo_variables.hpp @@ -0,0 +1,183 @@ + +#pragma once + +#include "vector_variables.hpp" +#include + +namespace motor +{ + namespace wire + { + template< typename T > + class variable< motor::math::m3d::transformation< T > > : public motor::wire::any + { + using base_t = motor::wire::any ; + + motor_this_typedefs( variable< motor::math::m3d::transformation< T > > ) ; + + public: + + motor_typedefs( motor::math::m3d::transformation< T >, value ) ; + + private: + + using pos_t = motor::wire::vec3v< T > ; + using scale_t = motor::wire::vec3v< T > ; + using axis_t = motor::wire::vec3v< T > ; + using angle_t = motor::wire::variable< T > ; + + using in_t = motor::wire::input_slot< value_t > ; + using out_t = motor::wire::output_slot< value_t > ; + + private: + + pos_t _pos = pos_t( "position", base_t::get_update_strategy() ) ; + scale_t _scale = scale_t( "scale", base_t::get_update_strategy() ) ; + axis_t _axis = axis_t( "axis", base_t::get_update_strategy() ) ; + angle_t _angle = angle_t( "angle" ) ; + + public: + + variable( char const * name ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) {} + variable( char const * name, value_cref_t v ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) + { + this_t::set_value( v ) ; + } + + variable( char const * name, value_cref_t v, motor::wire::sub_update_strategy const us ) noexcept : + base_t( name, motor::shared( in_t() ), motor::shared( out_t() ), us ) + { + this_t::set_value( v ) ; + } + + variable( this_cref_t ) = delete ; + variable( this_rref_t rhv ) noexcept : + base_t( std::move( rhv ) ), + _pos( std::move( rhv._pos ) ), _scale( std::move( rhv._scale ) ), + _axis( std::move( rhv._axis ) ), _angle( std::move( rhv._angle ) ) {} + + virtual ~variable( void_t ) noexcept {} + + public: + + virtual bool_t update( void_t ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + // wire exchanged via "push" + // pulling data is not required. + //in_->exchange() ; + + if ( value_t v; in_->get_value_and_reset( v ) ) + { + *out_ = v ; + this_t::propagate_value_to_sub( v ) ; + return true ; + } + else if ( motor::math::vec4b_t( _pos.update(), _scale.update(), + _axis.update(), _angle.update() ).any() ) + { + auto const p = _pos.get_value() ; + auto const s = _scale.get_value() ; + auto const ax = _axis.get_value() ; + auto const an = _angle.get_value() ; + + this_t::value_t const trafo( s, motor::math::vector_is_normalized( motor::math::vector4( ax, an ) ), p ) ; + + this_t::set_value( trafo ) ; + + return true ; + } + + return false ; + } + + virtual void_t update_strat_changed( motor::wire::sub_update_strategy const us ) noexcept + { + base_t::set_update_strategy( us ) ; + _pos.set_update_strategy( us ) ; + _scale.set_update_strategy( us ) ; + _axis.set_update_strategy( us ) ; + _angle.set_update_strategy( us ) ; + } + + bool_t update( motor::wire::sub_update_strategy const us ) noexcept + { + + } + + value_cref_t get_value( void_t ) const noexcept + { + return base_t::borrow_os()->get_value() ; + } + + // if the transformation is updated, other + // costly functions are called. So only use + // if really required. + void_t set_value( value_cref_t v ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + in_->set_value( v ) ; + out_->set_value( v ) ; + } + + private: + + void_t propagate_value_to_sub( value_cref_t v ) noexcept + { + auto const strat = base_t::get_update_strategy() ; + + if ( strat == motor::wire::sub_update_strategy::never ) + return ; + + _pos.set_value( v.get_translation() ) ; + + // some cost involved! + _scale.set_value( v.get_scale() ) ; + + // some cost involved! + { + auto const orientation = v.get_orientation() ; + _axis.set_value( orientation.xyz() ) ; + _angle.set_value( orientation.w() ) ; + } + + { + auto const r = v.get_rotation_matrix() ; + _axis.set_value( r.rotation_axis() ) ; + _angle.set_value( r.angle() ) ; + } + } + + private: + + virtual void_t for_each_member( for_each_funk_t f, motor::wire::any::member_info_in_t ifo ) noexcept + { + { + motor::string_t const full_name = ifo.full_name + "." + _pos.name() ; + f( _pos, { ifo.level, full_name } ) ; + motor::wire::any::derived_accessor( _pos ).for_each_member( f, { ifo.level + 1, full_name } ) ; + } + + { + motor::string_t const full_name = ifo.full_name + "." + _axis.name() ; + f( _axis, { ifo.level, full_name } ) ; + motor::wire::any::derived_accessor( _axis ).for_each_member( f, { ifo.level + 1, full_name } ) ; + } + + { + motor::string_t const full_name = ifo.full_name + "." + _angle.name() ; + f( _angle, { ifo.level, full_name } ) ; + motor::wire::any::derived_accessor( _angle ).for_each_member( f, { ifo.level + 1, full_name } ) ; + } + } + + } ; + motor_typedefs( variable< motor::math::m3d::transformation< float_t > >, trafo3fv ) ; + } +} \ No newline at end of file diff --git a/wire/variables/vector_variables.hpp b/wire/variables/vector_variables.hpp new file mode 100644 index 0000000..2fea5e5 --- /dev/null +++ b/wire/variables/vector_variables.hpp @@ -0,0 +1,356 @@ + + + +#pragma once + +#include "../variable.hpp" +#include +#include +#include + +namespace motor +{ + namespace wire + { + template< typename T > + class variable< motor::math::vector2< T > > : public motor::wire::any + { + using base_t = motor::wire::any ; + + motor_this_typedefs( variable< motor::math::vector2< T > > ) ; + motor_typedefs( motor::math::vector2< T >, value ) ; + + private: + + using in_t = motor::wire::input_slot< value_t > ; + using out_t = motor::wire::output_slot< value_t > ; + + using x_t = motor::wire::variable< T > ; + using y_t = motor::wire::variable< T > ; + + x_t _x = x_t( "x" ) ; + y_t _y = y_t( "y" ) ; + + public: + + variable( char const * const name ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) {} + + variable( char const * const name, motor::wire::sub_update_strategy const us ) noexcept : + base_t( name, motor::shared( in_t() ), motor::shared( out_t() ), us ) {} + + variable( this_cref_t ) = delete ; + variable( this_rref_t rhv ) noexcept : + base_t( std::move( rhv ) ), + _x( std::move( rhv._x ) ), _y( std::move( rhv._y ) ) {} + + virtual ~variable( void_t ) noexcept {} + + public: + + virtual bool_t update( void_t ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + // wire exchanged via "push" + // pulling data is not required. + //in_->exchange() ; + + if ( value_t a; in_->get_value_and_reset( a ) ) + { + *out_ = a ; + this_t::propagate_value_to_sub( a ) ; + return true ; + } + else if ( motor::math::vec2b_t( + _x.update(), _y.update() ).any() ) + { + value_t const v ( _x.get_value(), _y.get_value() ) ; + in_->set_value( v ) ; + *out_ = v ; + return true ; + } + + return false ; + } + + virtual void_t update_strat_changed( motor::wire::sub_update_strategy const us ) noexcept + { + base_t::set_update_strategy( us ) ; + _x.set_update_strategy( us ) ; + _y.set_update_strategy( us ) ; + } + + value_cref_t get_value( void_t ) const noexcept + { + return base_t::borrow_os()->get_value() ; + } + + void_t set_value( value_cref_t v ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + in_->set_value( v ) ; + out_->set_value( v ) ; + } + + private: + + void_t propagate_value_to_sub( value_cref_t v ) noexcept + { + _x.set_value( v.x() ) ; + _y.set_value( v.y() ) ; + } + + private: + + virtual void_t for_each_member( for_each_funk_t f, motor::wire::any::member_info_in_t ifo ) noexcept + { + f( _x, { ifo.level + 1, ifo.full_name + "." + _x.name() } ) ; + f( _y, { ifo.level + 1, ifo.full_name + "." + _y.name() } ) ; + } + }; + + template< typename T > + class variable< motor::math::vector3< T > > : public motor::wire::any + { + using base_t = motor::wire::any ; + + motor_this_typedefs( variable< motor::math::vector3< T > > ) ; + motor_typedefs( motor::math::vector3< T >, value ) ; + + private: + + using in_t = motor::wire::input_slot< value_t > ; + using out_t = motor::wire::output_slot< value_t > ; + + using x_t = motor::wire::variable< T > ; + using y_t = motor::wire::variable< T > ; + using z_t = motor::wire::variable< T > ; + + x_t _x = x_t( "x" ) ; + y_t _y = y_t( "y" ) ; + z_t _z = z_t( "z" ) ; + + public: + + variable( char const * const name ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) {} + + variable( char const * const name, motor::wire::sub_update_strategy const us ) noexcept : + base_t( name, motor::shared( in_t() ), motor::shared( out_t() ), us ) {} + + variable( this_cref_t ) = delete ; + variable( this_rref_t rhv ) noexcept : + base_t( std::move( rhv ) ), + _x( std::move( rhv._x ) ), _y( std::move( rhv._y ) ), + _z( std::move( rhv._z ) ) {} + + virtual ~variable( void_t ) noexcept {} + + public: + + virtual bool_t update( void_t ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + // wire exchanged via "push" + // pulling data is not required. + //in_->exchange() ; + + if ( value_t a; in_->get_value_and_reset( a ) ) + { + *out_ = a ; + this_t::propagate_value_to_sub( a ) ; + return true ; + } + else if ( motor::math::vec3b_t( + _x.update(), _y.update(), _z.update() ).any() ) + { + value_t const v ( _x.get_value(), _y.get_value(), _z.get_value() ) ; + in_->set_value( v ) ; + *out_ = v ; + return true ; + } + + return false ; + } + + virtual void_t update_strat_changed( motor::wire::sub_update_strategy const us ) noexcept + { + base_t::set_update_strategy( us ) ; + _x.set_update_strategy( us ) ; + _y.set_update_strategy( us ) ; + _z.set_update_strategy( us ) ; + } + + value_cref_t get_value( void_t ) const noexcept + { + return base_t::borrow_os()->get_value() ; + } + + void_t set_value( value_cref_t v ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + in_->set_value( v ) ; + out_->set_value( v ) ; + } + + private: + + void_t propagate_value_to_sub( value_cref_t v ) noexcept + { + _x.set_value( v.x() ) ; + _y.set_value( v.y() ) ; + _z.set_value( v.z() ) ; + } + + private: + + virtual void_t for_each_member( for_each_funk_t f, motor::wire::any::member_info_in_t ifo ) noexcept + { + f( _x, { ifo.level + 1, ifo.full_name + "." + _x.name() } ) ; + f( _y, { ifo.level + 1, ifo.full_name + "." + _y.name() } ) ; + f( _z, { ifo.level + 1, ifo.full_name + "." + _z.name() } ) ; + } + }; + + template< typename T > + class variable< motor::math::vector4< T > > : public motor::wire::any + { + using base_t = motor::wire::any ; + + motor_this_typedefs( variable< motor::math::vector4< T > > ) ; + motor_typedefs( motor::math::vector4< T >, value ) ; + + private: + + using in_t = motor::wire::input_slot< value_t > ; + using out_t = motor::wire::output_slot< value_t > ; + + using x_t = motor::wire::variable< T > ; + using y_t = motor::wire::variable< T > ; + using z_t = motor::wire::variable< T > ; + using w_t = motor::wire::variable< T > ; + + x_t _x = x_t( "x" ) ; + y_t _y = y_t( "y" ) ; + z_t _z = z_t( "z" ) ; + w_t _w = z_t( "w" ) ; + + public: + + variable( char const * const name ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) {} + + variable( char const * const name, motor::wire::sub_update_strategy const us ) noexcept : + base_t( name, motor::shared( in_t() ), motor::shared( out_t() ), us ) {} + + variable( this_cref_t ) = delete ; + variable( this_rref_t rhv ) noexcept : + base_t( std::move( rhv ) ), + _x( std::move( rhv._x ) ), _y( std::move( rhv._y ) ), + _z( std::move( rhv._z ) ), _w( std::move( rhv._w ) ) {} + + virtual ~variable( void_t ) noexcept {} + + public: + + virtual bool_t update( void_t ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + // wire exchanged via "push" + // pulling data is not required. + //in_->exchange() ; + + if ( value_t a; in_->get_value_and_reset( a ) ) + { + *out_ = a ; + this_t::propagate_value_to_sub( a ) ; + return true ; + } + else if ( motor::math::vec4b_t( + _x.update(), _y.update(), _z.update(), _w.update() ).any() ) + { + value_t const v ( _x.get_value(), _y.get_value(), _z.get_value(), , _w.get_value() ) ; + in_->set_value( v ) ; + *out_ = v ; + return true ; + } + + return false ; + } + + virtual void_t update_strat_changed( motor::wire::sub_update_strategy const us ) noexcept + { + base_t::set_update_strategy( us ) ; + _x.set_update_strategy( us ) ; + _y.set_update_strategy( us ) ; + _z.set_update_strategy( us ) ; + _w.set_update_strategy( us ) ; + } + + value_cref_t get_value( void_t ) const noexcept + { + return base_t::borrow_os()->get_value() ; + } + + void_t set_value( value_cref_t v ) noexcept + { + auto in_ = base_t::borrow_is() ; + auto out_ = base_t::borrow_os() ; + + in_->set_value( v ) ; + out_->set_value( v ) ; + } + + private: + + void_t propagate_value_to_sub( value_cref_t v ) noexcept + { + _x.set_value( v.x() ) ; + _y.set_value( v.y() ) ; + _z.set_value( v.z() ) ; + _w.set_value( v.w() ) ; + } + + private: + + virtual void_t for_each_member( for_each_funk_t f, motor::wire::any::member_info_in_t ifo ) noexcept + { + f( _x, { ifo.level + 1, ifo.full_name + "." + _x.name() } ) ; + f( _y, { ifo.level + 1, ifo.full_name + "." + _y.name() } ) ; + f( _z, { ifo.level + 1, ifo.full_name + "." + _z.name() } ) ; + f( _w, { ifo.level + 1, ifo.full_name + "." + _w.name() } ) ; + } + }; + + template< typename T > + using vec2v = motor::wire::variable< motor::math::vector2< T > > ; + + template< typename T > + using vec3v = motor::wire::variable< motor::math::vector3< T > > ; + + template< typename T > + using vec4v = motor::wire::variable< motor::math::vector4< T > > ; + + motor_typedefs( variable< motor::math::vector2< float_t > >, vec2fv ) ; + motor_typedefs( variable< motor::math::vector3< float_t > >, vec3fv ) ; + motor_typedefs( variable< motor::math::vector4< float_t > >, vec4fv ) ; + + motor_typedefs( variable< motor::math::vector2< int_t > >, vec2iv ) ; + motor_typedefs( variable< motor::math::vector3< int_t > >, vec3iv ) ; + motor_typedefs( variable< motor::math::vector4< int_t > >, vec4iv ) ; + + motor_typedefs( variable< motor::math::vector2< uint_t > >, vec2uiv ) ; + motor_typedefs( variable< motor::math::vector3< uint_t > >, vec3uiv ) ; + motor_typedefs( variable< motor::math::vector4< uint_t > >, vec4uiv ) ; + } +} \ No newline at end of file