Main Page · Modules · All Classes · Class Hierarchy
MAValueGenerators.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MAValueGenerators.hpp"
23 
24 #include <boost/math/constants/constants.hpp>
25 
26 #include <MCLog.hpp>
27 #include <MCThreadLocalData.hpp>
28 #include <MCTimer.hpp>
29 
30 #include "MADevice.hpp"
31 #include "MARandomness.hpp"
32 
33 MAGeneratorBase::MAGeneratorBase(float min, float max) : MinValue(min), MaxValue(max),
34  Duration(0), Timer(new MCTimer), Function(Linear)
35 {
36 }
37 
38 
39 MAGeneratorBase::~MAGeneratorBase()
40 {
41 }
42 
43 
45 {
46  MA_RANDOM_POINT_1(TransferFunction, (int)MAGeneratorBase::FunctionTypeMin,
47  (int)MAGeneratorBase::FunctionTypeMax);
48 
49  return (FunctionType)TransferFunction;
50 }
51 
52 
54 {
56 }
57 
58 
60 {
61  return Timer->GetStartTime();
62 }
63 
64 
66 {
67  return Timer->GetElapsedTime();
68 }
69 
70 
72 {
73  return Duration;
74 }
75 
76 
78 {
79  if (scale <= 0 || scale == 1.0 || Duration < 0)
80  return;
81 
82  Duration = (int)((float)Duration*scale);
83 }
84 
85 
87 {
88  return MinValue;
89 }
90 
91 
92 void MAGeneratorBase::SetMinValue(float min_value)
93 {
94  if (MCIsFloatInfinity(min_value))
95  return;
96 
97  MinValue = min_value;
98 }
99 
100 
102 {
103  return MaxValue;
104 }
105 
106 
107 void MAGeneratorBase::SetMaxValue(float max_value)
108 {
109  if (MCIsFloatInfinity(max_value))
110  return;
111 
112  MaxValue = max_value;
113 }
114 
115 
117 {
118  Function = function;
119 }
120 
121 
123 {
124  return Timer->IsStarted();
125 }
126 
127 
129 {
130  if (unlikely(MCIsFloatInfinity(GetMinValue())))
131  {
132  MC_WARNING("The minimum (start) value of the value generator has not been initialized yet.");
133  return;
134  }
135  if (unlikely(MCIsFloatInfinity(GetMaxValue())))
136  {
137  MC_WARNING("The maximum (target) value of the value generator has not been initialized yet.");
138  return;
139  }
140 
141  // It does not matter how we start the timer as we are interested only
142  // in the elapsed time for the value generation
143  Timer->Start();
144 }
145 
146 
147 void MAGeneratorBase::Start(float value)
148 {
149  if (unlikely(MCIsFloatInfinity(GetMinValue())))
150  {
151  MC_WARNING("The minimum (start) value of the value generator has not been initialized yet.");
152  return;
153  }
154  if (unlikely(MCIsFloatInfinity(GetMaxValue())))
155  {
156  MC_WARNING("The maximum (target) value of the value generator has not been initialized yet.");
157  return;
158  }
159  if (!CheckValueRange(value, true))
160  {
161  // It does not matter how the timer is started as we are interested only
162  // in the elapsed time for the value generation.
163  Timer->Start();
164  return;
165  }
166  int StartTime = 0;
167 
168  StartTime = (int)((float)(value-GetMinValue()) / (GetMaxValue()-GetMinValue())*Duration);
169  Timer->Start(StartTime);
170 }
171 
172 
173 void MAGeneratorBase::StartFromTime(int start_time)
174 {
175  if (unlikely(MCIsFloatInfinity(GetMinValue())))
176  {
177  MC_WARNING("The minimum (start) value of the value generator has not been initialized yet.");
178  return;
179  }
180  if (unlikely(MCIsFloatInfinity(GetMaxValue())))
181  {
182  MC_WARNING("The maximum (target) value of the value generator has not been initialized yet.");
183  return;
184  }
185 
186  Timer->StartFromTime(start_time);
187 }
188 
189 
191 {
192  return GetOverTime() > 0;
193 }
194 
195 
196 float MAGeneratorBase::GetTransformedValue(float value) const
197 {
198  if (likely(Function == Linear || MinValue == MaxValue))
199  return value;
200 
201  // Normalize the value interval to [0; π / 2]
202  float NormalizedValue = (value-GetMinValue())*(boost::math::constants::pi<float>() / 2) /
203  (GetMaxValue()-GetMinValue());
204 
206  {
207  return MinValue+sinf(NormalizedValue)*(GetMaxValue()-GetMinValue());
208  }
209 
210  // Function == AcceleratingSines
211  return MinValue+(1.0-sinf(boost::math::constants::pi<float>() / 2+NormalizedValue))*
212  (GetMaxValue()-GetMinValue());
213 }
214 
215 
216 bool MAGeneratorBase::CheckValueRange(float value, bool verbose)
217 {
218  if (!MCRangeCheck(value, MinValue, MaxValue))
219  {
220  if (verbose)
221  {
222  MC_WARNING("The value is out of the generator range %1.2f ∉ [%1.2f, %1.2f]",
223  value, MinValue, MaxValue);
224  }
225  return false;
226  }
227  return true;
228 }
229 
230 
232 {
233  Duration = duration;
234 }
235 
236 
237 void MADelayGenerator::SetMinValue(float min_value)
238 {
239  MAGeneratorBase::SetMinValue(min_value);
240  MAGeneratorBase::SetMaxValue(min_value);
241 }
242 
243 
244 void MADelayGenerator::SetMaxValue(float max_value)
245 {
246  MAGeneratorBase::SetMinValue(max_value);
247  MAGeneratorBase::SetMaxValue(max_value);
248 }
249 
250 
252 {
253  Timer->Start();
254 }
255 
256 
257 void MADelayGenerator::Start(float value)
258 {
259  MC_UNUSED(value)
260 
261  Timer->Start();
262 }
263 
264 
266 {
267  Timer->StartFromTime(start_time);
268 }
269 
270 
272 {
273  // The minimal and maximal values are the same
274  return GetMinValue();
275 }
276 
277 
279 {
280  if (Duration < 0 || !IsStarted())
281  {
282  return 0;
283  }
284  int ElapsedTime = (int)Timer->GetElapsedTime();
285 
286  if (ElapsedTime >= Duration)
287  {
288  return ElapsedTime-Duration;
289  }
290  return 0;
291 }
292 
293 
294 MASimpleGenerator::MASimpleGenerator(float min, float max, int duration) :
295  MAGeneratorBase(min, max)
296 {
297  Duration = duration;
298 }
299 
300 
301 MASimpleGenerator::MASimpleGenerator(float max, int duration) :
303 {
304  Duration = duration;
305 }
306 
307 
309 {
311  {
312  return MCFloatInfinity();
313  }
314  int ElapsedTime = Timer->GetElapsedTime();
315  float Ret = 0.0;
316 
317  if (ElapsedTime >= Duration)
318  {
319  Ret = GetMaxValue();
320  } else {
321  Ret = GetTransformedValue(GetMinValue()+(float)ElapsedTime / Duration*(GetMaxValue()-GetMinValue()));
322  }
323  return Ret;
324 }
325 
326 
328 {
329  if (!IsStarted())
330  {
331  return 0;
332  }
333  int ElapsedTime = (int)Timer->GetElapsedTime();
334 
335  if (ElapsedTime >= Duration)
336  {
337  return ElapsedTime-Duration;
338  }
339  return 0;
340 }
341 
342 
343 MAPeriodicGenerator::MAPeriodicGenerator(float min, float max, int dur1, int dur2, int dur3,
344  int dur4, int dur5, bool loop) :
345  MAGeneratorBase(min, max)
346 {
347  Duration1 = dur1;
348  Duration2 = dur2;
349  Duration3 = dur3;
350  Duration4 = dur4;
351  Duration5 = dur5;
352  Loop = loop;
353  if (Loop)
354  {
355  Duration = -2;
356  } else {
358  }
359  Timer->SetDuration(Duration);
360 }
361 
362 
363 MAPeriodicGenerator::MAPeriodicGenerator(float max, int dur1, int dur2, int dur3, int dur4,
364  int dur5, bool loop) :
366 {
367  Duration1 = dur1;
368  Duration2 = dur2;
369  Duration3 = dur3;
370  Duration4 = dur4;
371  Duration5 = dur5;
372  Loop = loop;
373  if (Loop)
374  {
375  Duration = -2;
376  } else {
378  }
379  Timer->SetDuration(Duration);
380 }
381 
382 
383 void MAPeriodicGenerator::Start(float value)
384 {
385  if (unlikely(MCIsFloatInfinity(GetMinValue())))
386  {
387  MC_WARNING("The minimum (start) value of the value generator has not been initialized yet.");
388  return;
389  }
390  if (unlikely(MCIsFloatInfinity(GetMaxValue())))
391  {
392  MC_WARNING("The maximum (target) value of the value generator has not been initialized yet.");
393  return;
394  }
395 
396  if (!CheckValueRange(value, true))
397  {
398  // It does not matter how we start the timer as we are interested only
399  // in the elapsed time for the value generation
400  Timer->Start();
401  return;
402  }
403  int StartTime = 0;
404 
405  StartTime = (int)((float)(value-GetMinValue()) / (GetMaxValue()-GetMinValue())*Duration2);
406  Timer->Start(StartTime+Duration1);
407 }
408 
409 
411 {
412  if (scale <= 0 || scale == 1.0 || Duration < 0)
413  return;
414 
415  Duration1 = (int)((float)Duration1*scale);
416  Duration2 = (int)((float)Duration2*scale);
417  Duration3 = (int)((float)Duration3*scale);
418  Duration4 = (int)((float)Duration4*scale);
419  Duration5 = (int)((float)Duration5*scale);
421 }
422 
423 
425 {
427  return MCFloatInfinity();
428 
429  int ElapsedTime = Timer->GetElapsedTime();
430  float Ret = 0.0;
431  int CurrentPeriod;
432 
433  if (Loop)
434  {
435  CurrentPeriod = ElapsedTime % (Duration1+Duration2+Duration3+Duration4+Duration5);
436  } else {
437  CurrentPeriod = ElapsedTime;
438  }
439 
440  if (CurrentPeriod < Duration1)
441  {
442  Ret = GetMinValue();
443  } else
444  if (CurrentPeriod < Duration1+Duration2)
445  {
446  Ret = GetTransformedValue(GetMinValue()+(float)(CurrentPeriod-Duration1) /
448  } else
449  if (CurrentPeriod < Duration1+Duration2+Duration3)
450  {
451  Ret = GetMaxValue();
452  } else
453  if (CurrentPeriod < Duration1+Duration2+Duration3+Duration4)
454  {
455  Ret = GetTransformedValue(GetMinValue()+(float)(1.0-((float)CurrentPeriod-Duration1-Duration2-Duration3) /
457  } else {
458  Ret = GetMinValue();
459  }
460  return Ret;
461 }
462 
463 
465 {
466  if (Loop || !IsStarted())
467  {
468  return 0;
469  }
470  int ElapsedTime = (int)Timer->GetElapsedTime();
471 
472  if (ElapsedTime >= Duration)
473  {
474  return ElapsedTime-Duration;
475  }
476  return 0;
477 }
478 
479 namespace
480 {
481 // Generator containers
483 // Verbose mode
484 MCThreadLocalData<bool> Verbose(true);
485 
486 void CheckStaticGeneratorContainerVariables()
487 {
488  if (unlikely(!Containers.get()))
489  {
490  Containers.reset(new MA::GeneratorContainerList);
491  Verbose.reset(new bool);
492  *Verbose = false;
493  }
494 }
495 }
496 
498  Device(nullptr), StartingValue(generator.GetMinValue()), CurrentValue(MCFloatInfinity()), TransitionName(""),
499  AlreadyExpired(false), ExpiredSignalBlockRefCount(0)
500 {
501  CheckStaticGeneratorContainerVariables();
502  Containers->push_back(this);
503  Generators.push_back(&generator);
504  if (*Verbose)
505  {
506  MC_LOG(std::string("Create container: "+MCToStr(this)).c_str());
507  }
508 }
509 
510 
512 {
513  if (*Verbose)
514  {
515  if (Device)
516  {
517  MC_LOG(std::string("Delete container ("+MCToStr(this)+", transition: "+
518  TransitionName+", owner: "+Device->GetDisplayName()+')').c_str());
519  } else {
520  MC_LOG(std::string("Delete container ("+MCToStr(this)+", transition: "+TransitionName+')').c_str());
521  }
522  }
524  {
525  (*ExpiredSignal).Emit(*this);
526  }
527 
528  // Remove the current instance from the global generator container list
529  Containers->erase(std::find(Containers->begin(), Containers->end(), this));
530 
531  for (unsigned int i = 0; i < Generators.size(); ++i)
532  {
533  delete Generators[i];
534  }
535  Generators.clear();
536 }
537 
538 
540 {
541  MC_LOG("----- Generatorcontainer list BEGIN -----");
542  MA::GeneratorContainerList& ContainerList = *Containers.get();
543 
544  for (auto& container : ContainerList)
545  {
546  MC_LOG(std::string("Container:"+MCToStr(container)).c_str());
547  }
548  for (auto& container : ContainerList)
549  {
550  // Block the "Expired" notification to avoid recursions/iterator problems
551  container->BlockExpiredSignal();
552  container->Dump();
553  container->UnblockExpiredSignal();
554  }
555  MC_LOG("----- Generatorcontainer list END -----");
556 }
557 
558 
560 {
561  CheckStaticGeneratorContainerVariables();
562  *Verbose = new_state;
563 }
564 
565 
567 {
568  Device = &owner;
569  if (*Verbose)
570  {
571  if (Device)
572  {
573  MC_LOG(std::string("New owner for the container ("+MCToStr(this)+", transition: "+
574  TransitionName+", owner: "+Device->GetDisplayName()+')').c_str());
575  } else {
576  MC_LOG(std::string("New owner for the container ("+MCToStr(this)+", transition: "+
577  TransitionName+')').c_str());
578  }
579  }
580 }
581 
582 
584 {
586 }
587 
588 
590 {
592 }
593 
594 
596 {
597  return ExpiredSignalBlockRefCount > 0;
598 }
599 
600 
601 void MAGeneratorContainer::SetTransitionName(const std::string& name)
602 {
603  TransitionName = name;
604 }
605 
606 
608 {
609  return TransitionName;
610 }
611 
612 
614 {
615  for (auto& generator : Generators)
616  {
617  // Search for the first non-delay generator and determinate if it is absolute or not
618  // Note: This check relies on the fact that only absolute generator can be added to an
619  // absolute container and non-absolute to a non-absolute container.
620  if (!dynamic_cast<MADelayGenerator*>(generator))
621  return generator->IsAbsolute();
622  }
623  // Case: The container contains only delay generators
624  return false;
625 }
626 
627 
629 {
630  int Duration = 0;
631 
632  for (auto& generator : Generators)
633  {
634  if (generator->GetDuration() < 0)
635  {
636  return -1;
637  }
638  Duration += generator->GetDuration();
639  }
640  return Duration;
641 }
642 
643 
645 {
646  if (scale <= 0 || scale == 1.0)
647  return;
648 
649  for (auto& generator : Generators)
650  {
651  if (generator->GetDuration() > 0)
652  {
653  generator->ScaleDuration(scale);
654  }
655  }
656 }
657 
658 
660 {
661  return GetDuration() >= 0;
662 }
663 
664 
666 {
667  return !IsFinite();
668 }
669 
670 
672 {
673  return Generators.size() > 0 && Generators[0]->IsStarted();
674 }
675 
676 
678 {
679  if (!IsStarted() || !IsFinite())
680  {
681  return false;
682  }
683  bool Expired = Generators.size() == 1 && Generators[0]->IsExpired();
684 
685  if (Expired && !AlreadyExpired && !IsExpiredSignalBlocked())
686  {
687  AlreadyExpired = true;
689  if (*Verbose)
690  {
691  if (Device)
692  {
693  MC_LOG(std::string("Container expired ("+MCToStr(this)+", transition: "+
694  TransitionName+", owner: "+Device->GetDisplayName()+')').c_str());
695  } else {
696  MC_LOG(std::string("Container expired ("+MCToStr(this)+", transition: "+TransitionName+')').c_str());
697  }
698  }
699  (*ExpiredSignal).Emit(*this);
701  }
702  return Expired;
703 }
704 
705 
707 {
708  return Generators.size() == 1;
709 }
710 
711 
713 {
714  for (auto& generator : Generators)
715  {
716  if (!dynamic_cast<MADelayGenerator*>(generator))
717  return true;
718  }
719  return false;
720 }
721 
722 
724 {
725  if (IsPermanent())
726  {
727  MC_WARNING("It is not allowed to add new generators to a permanent container.");
728  return;
729  }
730  // Set the start value of the new generator if needs be
731  if (!in_front && MCIsFloatInfinity(generator.GetMinValue()) && !MCIsFloatInfinity(GetTargetValue()))
732  {
733  generator.SetMinValue(GetTargetValue());
734  }
735  if (HasRealGenerator() && !IsAbsolute() && generator.IsAbsolute() &&
736  !dynamic_cast<MADelayGenerator*>(&generator) &&
737  GetTargetValue() != generator.GetMinValue())
738  {
739  MC_WARNING("It is not allowed to add an absolute generator to a relative container.");
740  return;
741  }
742  if (HasRealGenerator() && IsAbsolute() && !generator.IsAbsolute())
743  {
744  MC_WARNING("It is not allowed to add a relative generator to an absolute container.");
745  return;
746  }
747  if (in_front)
748  {
749  Generators.insert(Generators.begin(), &generator);
750  } else {
751  Generators.push_back(&generator);
752  }
753 }
754 
755 
756 void MAGeneratorContainer::ScaleGenerators(float min, float max, float new_max)
757 {
758  for (auto& generator : Generators)
759  {
760  float NewMinValue = MCScaleValue(generator->GetMinValue(), min, max, new_max);
761  float NewMaxValue = MCScaleValue(generator->GetMaxValue(), min, max, new_max);
762 
763  generator->SetMinValue(NewMinValue);
764  generator->SetMaxValue(NewMaxValue);
765  }
766 }
767 
768 
769 void MAGeneratorContainer::Start(float device_value)
770 {
771  if (Generators[0]->IsStarted())
772  return;
773 
774  if (unlikely(MCIsFloatInfinity(StartingValue)))
775  {
776  if (MCIsFloatInfinity(Generators[0]->GetMinValue()))
777  {
778  StartingValue = device_value;
779  } else {
780  StartingValue = Generators[0]->GetMinValue();
781  }
782  }
783 
784  if (!(dynamic_cast<MADelayGenerator*>(Generators[0]) && MCIsFloatInfinity(CurrentValue)))
785  {
786  if (unlikely(MCIsFloatInfinity(Generators[0]->GetMinValue())))
787  {
788  Generators[0]->SetMinValue(device_value);
789  }
790  if (unlikely(MCIsFloatInfinity(Generators[0]->GetMaxValue())))
791  {
792  Generators[0]->SetMaxValue(device_value);
793  }
794  }
795  Generators[0]->Start();
796  if (*Verbose)
797  {
798  if (Device)
799  {
800  MC_LOG(std::string("Container started ("+MCToStr(this)+", transition: "+
801  TransitionName+", owner: "+Device->GetDisplayName()+')').c_str());
802  } else {
803  MC_LOG(std::string("Container started ("+MCToStr(this)+", transition: "+TransitionName+')').c_str());
804  }
805  }
806 }
807 
808 
810 {
811  if (!IsStarted() || IsExpired())
812  return;
813  float OldValue = MCFloatInfinity();
814 
815  // Remove the expired top generator if possible
816  while (Generators[0]->IsExpired() && Generators.size() > 1)
817  {
818  // Store the last generated value
819  OldValue = Generators[0]->GetCurrentValue();
820  if (MCIsFloatInfinity(Generators[1]->GetMinValue()))
821  {
822  if (MCIsFloatInfinity(OldValue) && !dynamic_cast<MADelayGenerator*>(Generators[1]))
823  {
824  // Case: Delay generator in the first position -> it keeps infinite min/max values
825  Generators[1]->SetMinValue(device_value);
826  } else {
827  Generators[1]->SetMinValue(OldValue);
828  }
829  }
830  if (MCIsFloatInfinity(Generators[1]->GetMaxValue()))
831  {
832  if (MCIsFloatInfinity(OldValue) && !dynamic_cast<MADelayGenerator*>(Generators[1]))
833  {
834  // Case: Delay generator in the first position -> it keeps infinite min/max values
835  Generators[1]->SetMaxValue(device_value);
836  } else {
837  Generators[1]->SetMaxValue(OldValue);
838  }
839  }
840  Generators[1]->StartFromTime(Generators[0]->GetStartTime()+Generators[0]->GetDuration());
841  delete Generators[0];
842  Generators.erase(Generators.begin());
843  }
844  if (!Generators[0]->IsStarted())
845  {
846  if (MCIsFloatInfinity(OldValue))
847  {
848  Start(device_value);
849  } else {
850  // Use the old generator last value
851  Start(OldValue);
852  }
853  }
854  CurrentValue = Generators[0]->GetCurrentValue();
855 }
856 
857 
859 {
860  if (IsExpired())
861  {
862  return GetTargetValue();
863  }
865  {
866  return Generators[0]->GetMinValue();
867  }
868  return CurrentValue;
869 }
870 
871 
873 {
874  return StartingValue;
875 }
876 
877 
879 {
880  return !MCIsFloatInfinity(StartingValue) ? StartingValue : Generators[0]->GetMaxValue();
881 }
882 
883 
885 {
886  MAGeneratorBase* Generator = Generators.back();
887 
888  // It is a simple generator
889  if (dynamic_cast<MASimpleGenerator*>(Generator))
890  {
891  return Generator->GetMaxValue();
892  }
893  // Otherwise a periodic generator or a delay generator
894  return Generator->GetMinValue();
895 }
896 
897 
899 {
900  AddGenerator(*new MADelayGenerator(-1));
901 }
902 
903 
905 {
906  std::string LogMessage;
907 
908  LogMessage = "Container ("+MCToStr(this)+", transition: "+TransitionName+"): ";
909  LogMessage += "start - "+MCToStr(GetStartingValue())+", ";
910  LogMessage += "target - "+MCToStr(GetTargetValue())+", ";
911  LogMessage += "permanent - "+MCToStr(IsPermanent())+", ";
912  LogMessage += "duration - "+MCToStr(GetDuration())+", ";
913  LogMessage += "started/expired - "+MCToStr(IsStarted())+'/'+MCToStr(IsExpired())+", ";
914  LogMessage += '(';
915  int i = 0;
916 
917  for (auto iter = Generators.begin(); iter != Generators.end(); ++iter)
918  {
919  i++;
920  LogMessage += MCToStr(i)+": ";
921  LogMessage += "min - "+MCToStr((*iter)->GetMinValue())+", ";
922  LogMessage += "max - "+MCToStr((*iter)->GetMaxValue())+", ";
923  LogMessage += "duration - "+MCToStr((*iter)->GetDuration())+", ";
924  LogMessage += "elapsed - "+MCToStr((*iter)->GetElapsedTime())+", ";
925  LogMessage += "started/expired - "+MCToStr((*iter)->IsStarted())+'/'+MCToStr((*iter)->IsExpired());
926  if (iter+1 != Generators.end())
927  LogMessage += " || ";
928  }
929  LogMessage += ')';
930  MC_LOG("%s", LogMessage.c_str());
931 }
float GetMinValue() const
Get the starting value of the generator.
Delay generator class.
void UnblockExpiredSignal()
Unblock the expiration signal of the container.
bool IsAbsolute() const
Check if the container is absolute.
bool IsExpired()
Check if the container has been expired.
virtual int GetDuration() const
Get the duration of the generator.
int Duration1
First segment duration (when it keeps the minimum value)
#define MA_RANDOM_POINT_1(_variable_name, _min, _max)
Set a random point with one value.
void AddGenerator(MAGeneratorBase &generator, bool in_front=false)
Add a new generator after the last internal generator.
void Dump()
Dump the internal generators in the container.
float GetDesiredStartingValue() const
Get the desired starting value of the container.
void SetTransferFunction(FunctionType function)
Set the transfer function.
virtual void SetMaxValue(float max_value) override
Set the target value of the generator.
float GetTargetValue() const
Get the final target value of the container.
int GetDuration() const
Get the container duration.
bool MCRangeCheck(const T &value, const T &min, const T &max)
Range check of a value.
Definition: MCDefs.hpp:544
int Duration3
Third segment duration (when it keeps the maximum value)
MADevice * Device
Owner device.
MAGeneratorContainer(MAGeneratorBase &generator)
Create a generator container with a generator.
MASimpleGenerator(float min, float max, int duration)
Creates a simple generator.
bool AlreadyExpired
Whenever it is expired already.
bool IsExpiredSignalBlocked() const
Check if the expiration signal of the container is blocked.
float MaxValue
Maximum value.
void CalculateCurrentValue(float device_value)
Calculate the current value based on a device value.
virtual void StartFromTime(int start_time) override
Start the generator from a certain time.
virtual void SetMaxValue(float max_value)
Set the target value of the generator.
bool IsPermanent() const
Check if the container is permanent.
std::string TransitionName
Transition name.
void MakePermanent()
Make the generator container infinite long (permanent)
float GetMaxValue() const
Get the target value of the generator.
float StartingValue
Starting value.
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
std::string MCToStr(const T value, bool hex_manipulator=false)
Convert an other type to string with std::stringstream.
Definition: MCDefs.hpp:360
int Duration5
Fifth segment duration (when it keeps the minimum value)
Device class.
Definition: MADevice.hpp:57
bool HasRealGenerator() const
Check if the container has any real generator other than delay generators.
virtual void ScaleDuration(float scale)
Scale the generator duration.
int Duration4
Fourth segment duration (when it interpolates back to the minimum value)
bool Loop
Whether the generator is looped.
void SetTransitionName(const std::string &name)
Set a transition name for the container.
boost::scoped_ptr< MCTimer > Timer
Timer.
MADelayGenerator(int duration)
Creates a delay generator.
virtual float GetCurrentValue() override
Get the current value.
FunctionType Function
Transfer function.
void Start(float device_value)
Start the first generator in the container based on a device value.
float MinValue
Minimum value.
float GetTransformedValue(float value) const
Get the transformed value for a derived generator.
static FunctionType GetRandomFunction()
Get a random generator function type.
bool IsStarted() const
Check if the container has been started.
bool MCIsFloatInfinity(const float value)
Check a value for float infinity.
Definition: MCDefs.cpp:122
#define MC_UNUSED(a)
Helper macro to avoid compiler warning about unused function parameters.
Definition: MCDefs.hpp:601
int GetStartTime() const
Get the start time of the generator.
bool IsAbsolute() const
Check if the generator is absolute.
void ScaleDuration(float scale)
Scale the generator durations in the container.
MASignal< MAGeneratorContainer & > ExpiredSignalType
Generator just expired signal type.
virtual void SetMinValue(float min_value) override
Set the starting value of the generator.
float GetCurrentValue()
Get the current value.
bool CheckValueRange(float value, bool verbose=true)
Check if a value falls into the valid generator value range.
virtual int GetOverTime() const override
Get the overtime after the generator has been expired.
int GetElapsedTime() const
Get the elapsed time of the generator.
virtual void Start() override
Start the generator.
float CurrentValue
Current value.
std::string GetTransitionName() const
Get the transition name where the container belongs to.
MAGeneratorBase(float min=MCFloatInfinity(), float max=MCFloatInfinity())
Create a base generator.
void SetOwnerDevice(MADevice &owner)
Set the owner device.
Base class for generators.
virtual void Start()
Start the generator.
bool IsFinite() const
Check if the container is finite.
Simple timer class with microsecond precision.
Definition: MCTimer.hpp:59
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
bool IsExpired() const
Check if the generator has been expired.
virtual int GetOverTime() const override
Get the overtime after the generator has been expired.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
void ScaleGenerators(float min, float max, float new_max)
Scale the internal generators into a new value range.
MAPeriodicGenerator(float min, float max, int dur1, int dur2, int dur3, int dur4, int dur5, bool loop=false)
Creates a periodic generator.
static void DumpAllContainers()
Dump all containers in the current run (the list is tls based thus per thread)
float GetStartingValue() const
Get the starting value of the container.
float MCScaleValue(float value, float min, float max, float new_max)
Scale a value to a new range.
Definition: MCDefs.cpp:154
~MAGeneratorContainer()
Destroy the generator container.
virtual void ScaleDuration(float scale) override
Scale the generator duration.
bool HasOneGenerator() const
Check if the container has only one generator internally.
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
virtual void SetMinValue(float min_value)
Set the starting value of the generator.
int ExpiredSignalBlockRefCount
Whenever the signal of the "just expiration" is blocked.
virtual float GetCurrentValue() override
Get the current value.
static void SetVerbose(bool new_state)
Set the verbosity of the generator containers.
int Duration
Duration.
int Duration2
Second segment duration (when it interpolates to the maximum value)
virtual void StartFromTime(int start_time)
Start the generator from a certain time.
MA::GeneratorList Generators
Value generators.
void BlockExpiredSignal()
Block the expiration signal of the container.
virtual int GetOverTime() const override
Get the overtime after the generator has been expired.
virtual int GetOverTime() const =0
Get the overtime after the generator has been expired.
bool IsStarted() const
Check if the generator has been started.
virtual float GetCurrentValue() override
Get the current value.