AnimNode.cpp
Go to the documentation of this file.
1 #include "AnimNode.hpp"
2 #include "AnimSystem.hpp"
3 
4 namespace iv
5 {
6 
8 
10  cm( inst, this, "AnimNode", ClientMarker::Status() ),
11  inst( inst ),
12  as( inst->getSystem< AnimSystem >() ),
13  _label(),
14  _speed( 1.0 ),
15  _anim_initialized( false ),
16  _parent( nullptr ),
17  _children(),
18  _activation_id( std::nullopt ),
19  _active_cooldown( 0 ),
20  _active( false ),
21  _distance_start( 0 ),
22  _distance_end( 0 ),
23  _distance_working( 0 ),
24  _requested_step( 0 ),
25  _update_id( std::nullopt ),
26  in_target_notified( false )
27 {
28  if( auto as = this->instance()->getSystem< AnimSystem >() )
29  as->InsertRoot( this );
30 }
31 
33 {
34  if( this->_parent )
35  this->_parent->anim_childDisconnect( this );
36  else if( auto as = this->instance()->getSystem< AnimSystem >() )
37  as->RemoveRoot( this );
38 
39  for( AnimConnector * child : this->_children )
40  child->anim_parentDisconnect( this );
41 }
42 
44 {
45  return this->inst;
46 }
47 
49 {
50  static iv::TableId DebugTable = TableId::create( "AnimNodeI" );
51 
52  auto row = view->Table( DebugTable ).Row( this );
53  row.Column( "label", this->label() );
54  row.Column( "speed", this->Speed() );
55  row.Column( "distance", this->Distance() );
56  row.Column( "parent/cnt", bool( this->_parent ) );
57  row.Column( "children/cnt", this->_children.size() );
58 }
59 
60 AnimNodeI * AnimNodeI::label( std::string const & val )
61 {
62  this->_label = val;
63  return this;
64 }
65 
66 std::string const & AnimNodeI::label() const
67 {
68  return this->_label;
69 }
70 
71 //====================================================================================
72 //------------------------------- Tree structure -------------------------------------
74 {
75  if( this->_parent )
76  {
77  this->cm.warning( SRC_INFO, "Can not set parent connector, nodes shoud only have one parent." );
78  return;
79  }
80 
81  if( !parent )
82  {
83  this->cm.warning( SRC_INFO, "Can not set nullptr parent connector, use anim_unsetParent instead." );
84  return;
85  }
86 
87  if( auto as = this->instance()->getSystem< AnimSystem >() )
88  as->RemoveRoot( this );
89 
90  this->_parent = parent;
91 }
92 
94 {
95  if( !this->_parent )
96  {
97  this->cm.warning( SRC_INFO, "Can not unset parent connector, this node currently has no parent." );
98  return;
99  }
100 
101  if( parent != this->_parent )
102  {
103  this->cm.warning( SRC_INFO, "Can not unset parent connector, this node has different parent." );
104  return;
105  }
106 
107  if( auto as = this->instance()->getSystem< AnimSystem >() )
108  as->RemoveRoot( this );
109 
110  this->_parent = nullptr;
111 }
112 
114 {
115  return this->_parent;
116 }
117 
119 {
120  this->_children.insert( child );
121 }
122 
124 {
125  this->_children.erase( child );
126 }
127 
128 void AnimNodeI::anim_eachChild( std::function< void( AnimConnector * ) > const & f )
129 {
130  for( AnimConnector * child : this->_children )
131  f( child );
132 }
133 
134 //============================================================================================================
135 //-------------------------- Animation update ----------------------------------------------------------------
137 {
138  //
139  this->_distance_start = this->_distance_end;
140  this->_distance_working = 0.0f;
141  this->_requested_step = 0.0f;
142  this->_update_id = this->as->update_id();
143 
144  //
145  this->cm.log( SRC_INFO, ::iv::Defs::Log::Animation_NodeUpdate, "UpdateStart | distance ",this->_distance_start, "." );
146 }
147 
149 {
150  //
151  this->_distance_end = this->_distance_working;
152  this->_update_id = std::nullopt;
153  this->UpdateLastTarget();
154 
155  //
156  bool in_target = this->IsInTarget();
157 
158  //
159  this->cm.log( SRC_INFO, ::iv::Defs::Log::Animation_NodeUpdate, "UpdateEnd | distance ", this->_distance_start," -> ", this->_distance_end, ", in_target ", in_target, "." );
160 
161  // inform parent connector about arrival to destination
162  if( in_target )
163  {
164  if( !this->in_target_notified )
165  if( AnimConnector * parent = this->anim_getParent() )
166  parent->childArrived_Set();
167  }
168  else
169  {
170  this->in_target_notified = false;
171  }
172 
173  // maybe deactivate node
174  if( in_target )
175  {
176  if( this->_active_cooldown > 1 )
177  {
178  this->_active_cooldown -= 1;
179  }
180  else
181  {
182  if( this->_active )
183  this->cm.log( SRC_INFO, ::iv::Defs::Log::Animation_Activations, "Deactivate node." );
184 
185  this->_active = false;
186  this->_active_cooldown = 0;
187  }
188  }
189  else
190  {
191  if( !this->_active )
192  this->cm.log( SRC_INFO, ::iv::Defs::Log::Animation_Activations, "Activate node." );
193  this->_active = true;
195  }
196 }
197 
198 std::optional< unsigned > AnimNodeI::System_UpdateId() const
199 {
200  return this->_update_id;
201 }
202 
204 {
205  this->_requested_step = step_distance * this->Speed();
206 }
207 
209 {
210  // scale distance
211  Anim_float new_distance_scaled = new_distance / this->Speed();
212  if( this->Speed() == std::numeric_limits< Anim_float >::infinity() )
213  new_distance_scaled = 0.0;
214 
215  // update distance
216  this->_distance_working = std::max( this->_distance_working, new_distance_scaled );
217 }
218 
220 {
221  if( !this->_anim_initialized )
222  {
223  this->_anim_initialized = true;
224  return std::numeric_limits< Anim_float >::infinity();
225  }
226 
227  return this->_requested_step;
228 }
229 
231 {
232  if( !this->_active && this->_activation_id.has_value() )
233  {
234  unsigned update_id = this->as->update_id();
235  if( this->_activation_id.value() == update_id )
236  {
237  this->cm.log( SRC_INFO, ::iv::Defs::Log::Animation_Activations, "Activate node." );
238  this->_activation_id = std::nullopt;
239  this->_active = true;
241  }
242  }
243 
244  return this->_active;
245 }
246 
248 {
249  // queue activation for next frame
250  if( !this->Active() )
251  this->_activation_id = this->as->update_id() + 1;
252  else
254 
255  // activate parent nodes
256  if( AnimConnector * parent = this->anim_getParent() )
257  {
258  parent->anim_eachParent(
259  [&]( AnimNodeI * node )
260  {
261  node->Activate();
262  }
263  );
264  }
265 }
266 
268 {
269  return this->_distance_end;
270 }
271 
273 {
274  return this->_speed;
275 }
276 
278 {
279  this->_speed = speed;
280  return this;
281 }
282 
284 {
285  this->_speed = std::numeric_limits< Anim_float >::infinity();
286  return this;
287 }
288 
290 {
291  return this->Distance() == Anim_float( 0.0 ) && this->TargetStabilized();
292 }
293 
294 }