]> git.sesse.net Git - casparcg/blob - core/producer/binding.h
[scene] Fixed double evaluation of expressions
[casparcg] / core / producer / binding.h
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG 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 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Helge Norberg, helge.norberg@svt.se
20 */
21
22 #pragma once
23
24 #include <functional>
25 #include <memory>
26 #include <vector>
27 #include <string>
28 #include <map>
29 #include <algorithm>
30 #include <type_traits>
31 #include <stdexcept>
32
33 #include <boost/lexical_cast.hpp>
34 #include <boost/utility/value_init.hpp>
35
36 #include <common/tweener.h>
37 #include <common/except.h>
38
39 namespace caspar { namespace core {
40
41 namespace detail {
42
43 struct impl_base : std::enable_shared_from_this<impl_base>
44 {
45         std::vector<std::shared_ptr<impl_base>> dependencies_;
46         mutable std::vector<std::pair<
47                         std::weak_ptr<void>,
48                         std::function<void ()>>> on_change_;
49
50         virtual ~impl_base()
51         {
52         }
53
54         virtual void evaluate() const = 0;
55
56         void depend_on(const std::shared_ptr<impl_base>& dependency)
57         {
58                 auto self = shared_from_this();
59
60                 if (dependency->depends_on(self))
61                         CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("Can't have circular dependencies between bindings"));
62
63                 dependency->on_change(self, [=] { evaluate(); });
64                 dependencies_.push_back(dependency);
65         }
66
67         bool depends_on(const std::shared_ptr<impl_base>& other) const
68         {
69                 for (auto& dependency : dependencies_)
70                 {
71                         if (dependency == other)
72                                 return true;
73
74                         if (dependency->depends_on(other))
75                                 return true;
76                 }
77
78                 return false;
79         }
80
81         void on_change(
82                         const std::weak_ptr<void>& dependant,
83                         const std::function<void ()>& listener) const
84         {
85                 on_change_.push_back(std::make_pair(dependant, listener));
86         }
87 };
88
89 }
90
91 template <typename T>
92 class binding
93 {
94 private:
95
96         struct impl : public detail::impl_base
97         {
98                 mutable T                       value_;
99                 std::function<T ()> expression_;
100                 mutable bool            evaluated_              = false;
101
102                 impl()
103                         : value_(boost::value_initialized<T>())
104                 {
105                 }
106
107                 impl(T value)
108                         : value_(value)
109                 {
110                 }
111
112                 template<typename Expr>
113                 impl(const Expr& expression)
114                         : value_(boost::value_initialized<T>())
115                         , expression_(expression)
116                 {
117                 }
118
119                 T get() const
120                 {
121                         if (!evaluated_)
122                                 evaluate();
123
124                         return value_;
125                 }
126
127                 bool bound() const
128                 {
129                         return static_cast<bool>(expression_);
130                 }
131
132                 void set(T value)
133                 {
134                         if (bound())
135                                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Bound value cannot be set"));
136
137                         if (value == value_)
138                                 return;
139
140                         value_ = value;
141
142                         on_change();
143                 }
144
145                 void evaluate() const override
146                 {
147                         if (bound())
148                         {
149                                 auto new_value = expression_();
150
151                                 evaluated_ = true;
152
153                                 if (new_value != value_)
154                                 {
155                                         value_ = new_value;
156                                         on_change();
157                                 }
158                         }
159                         else
160                                 evaluated_ = true;
161                 }
162
163                 using impl_base::on_change;
164                 void on_change() const
165                 {
166                         auto copy = on_change_;
167
168                         for (int i = static_cast<int>(copy.size()) - 1; i >= 0; --i)
169                         {
170                                 auto strong = copy[i].first.lock();
171
172                                 if (strong)
173                                         copy[i].second();
174                                 else
175                                         on_change_.erase(on_change_.begin() + i);
176                         }
177                 }
178
179                 void bind(const std::shared_ptr<impl>& other)
180                 {
181                         unbind();
182                         depend_on(other);
183                         expression_ = [other]{ return other->get(); };
184                         evaluate();
185                 }
186
187                 void unbind()
188                 {
189                         if (bound())
190                         {
191                                 expression_ = std::function<T ()>();
192                                 dependencies_.clear();
193                         }
194                 }
195         };
196
197         template<typename> friend class binding;
198
199         std::shared_ptr<impl> impl_;
200 public:
201         binding()
202                 : impl_(new impl)
203         {
204         }
205
206         explicit binding(T value)
207                 : impl_(new impl(value))
208         {
209         }
210
211         // Expr -> T ()
212         template<typename Expr>
213         explicit binding(const Expr& expression)
214                 : impl_(new impl(expression))
215         {
216                 //impl_->evaluate();
217         }
218
219         // Expr -> T ()
220         template<typename Expr, typename T2>
221         binding(const Expr& expression, const binding<T2>& dep)
222                 : impl_(new impl(expression))
223         {
224                 depend_on(dep);
225                 //impl_->evaluate();
226         }
227
228         // Expr -> T ()
229         template<typename Expr, typename T2, typename T3>
230         binding(
231                         const Expr& expression,
232                         const binding<T2>& dep1,
233                         const binding<T3>& dep2)
234                 : impl_(new impl(expression))
235         {
236                 depend_on(dep1);
237                 depend_on(dep2);
238                 //impl_->evaluate();
239         }
240
241         void* identity() const
242         {
243                 return impl_.get();
244         }
245
246         T get() const
247         {
248                 return impl_->get();
249         }
250
251         void set(T value)
252         {
253                 impl_->set(value);
254         }
255
256         void bind(const binding<T>& other)
257         {
258                 impl_->bind(other.impl_);
259         }
260
261         bool bound() const
262         {
263                 return impl_->bound();
264         }
265
266         template<typename T2>
267         void depend_on(const binding<T2>& other)
268         {
269                 impl_->depend_on(other.impl_);
270         }
271
272         binding<T> operator+(T other) const
273         {
274                 return transformed([other](T self) { return self + other; });
275         }
276
277         binding<T> operator+(const binding<T>& other) const
278         {
279                 return composed(other, [](T self, T o) { return self + o; });
280         }
281
282         binding<T>& operator++()
283         {
284                 T new_value = get();
285                 ++new_value;
286
287                 set(new_value);
288
289                 return *this;
290         }
291
292         binding<T> operator++(int)
293         {
294                 binding<T> pre_val(get());
295                 ++*this;
296
297                 return pre_val;
298         }
299
300         binding<T> operator-() const
301         {
302                 return transformed([](T self) { return -self; });
303         }
304
305         binding<T> operator-(const binding<T>& other) const
306         {
307                 return *this + -other;
308         }
309
310         binding<T> operator-(T other) const
311         {
312                 return *this + -other;
313         }
314
315         binding<T>& operator--()
316         {
317                 T new_value = get();
318                 --new_value;
319
320                 set(new_value);
321
322                 return *this;
323         }
324
325         binding<T> operator--(int)
326         {
327                 binding<T> pre_val(get());
328                 --*this;
329
330                 return pre_val;
331         }
332
333         binding<T> operator*(T other) const
334         {
335                 return transformed([other](T self) { return self * other; });
336         }
337
338         binding<T> operator*(const binding<T>& other) const
339         {
340                 return composed(other, [](T self, T o) { return self * o; });
341         }
342
343         binding<T> operator/(T other) const
344         {
345                 return transformed([other](T self) { return self / other; });
346         }
347
348         binding<T> operator/(const binding<T>& other) const
349         {
350                 return composed(other, [](T self, T o) { return self / o; });
351         }
352
353         binding<T> operator%(T other) const
354         {
355                 return transformed([other](T self) { return self % other; });
356         }
357
358         binding<T> operator%(const binding<T>& other) const
359         {
360                 return composed(other, [](T self, T o) { return self % o; });
361         }
362
363         binding<bool> operator==(T other) const
364         {
365                 return transformed([other](T self) { return self == other; });
366         }
367
368         binding<bool> operator==(const binding<T>& other) const
369         {
370                 return composed(other, [](T self, T o) { return self == o; });
371         }
372
373         binding<bool> operator!=(T other) const
374         {
375                 return transformed([other](T self) { return self != other; });
376         }
377
378         binding<bool> operator!=(const binding<T>& other) const
379         {
380                 return composed(other, [](T self, T o) { return self != o; });
381         }
382
383         binding<bool> operator<(T other) const
384         {
385                 return transformed([other](T self) { return self < other; });
386         }
387
388         binding<bool> operator<(const binding<T>& other) const
389         {
390                 return composed(other, [](T self, T o) { return self < o; });
391         }
392
393         binding<bool> operator>(T other) const
394         {
395                 return transformed([other](T self) { return self > other; });
396         }
397
398         binding<bool> operator>(const binding<T>& other) const
399         {
400                 return composed(other, [](T self, T o) { return self > o; });
401         }
402
403         binding<bool> operator<=(T other) const
404         {
405                 return transformed([other](T self) { return self <= other; });
406         }
407
408         binding<bool> operator<=(const binding<T>& other) const
409         {
410                 return composed(other, [](T self, T o) { return self <= o; });
411         }
412
413         binding<bool> operator>=(T other) const
414         {
415                 return transformed([other](T self) { return self >= other; });
416         }
417
418         binding<bool> operator>=(const binding<T>& other) const
419         {
420                 return composed(other, [](T self, T o) { return self >= o; });
421         }
422
423         template<typename T2>
424         typename std::enable_if<
425                         std::is_same<T, T2>::value,
426                         binding<T2>
427                 >::type as() const
428         {
429                 return *this;
430         }
431
432         template<typename T2>
433         typename std::enable_if<
434                         (std::is_arithmetic<T>::value || std::is_same<bool, T>::value) && (std::is_arithmetic<T2>::value || std::is_same<bool, T2>::value) && !std::is_same<T, T2>::value,
435                         binding<T2>
436                 >::type as() const
437         {
438                 return transformed([](T val) { return static_cast<T2>(val); });
439         }
440
441         template<typename T2>
442         typename std::enable_if<
443                         (std::is_same<std::wstring, T>::value || std::is_same<std::wstring, T2>::value) && !std::is_same<T, T2>::value,
444                         binding<T2>
445                 >::type as() const
446         {
447                 return transformed([](T val) { return boost::lexical_cast<T2>(val); });
448         }
449
450         // Func -> R (T self_val)
451         // Returns binding<R>
452         template<typename Func>
453         auto transformed(const Func& func) const -> binding<decltype(func(impl_->value_))>
454         {
455                 typedef decltype(func(impl_->value_)) R;
456                 auto self = impl_;
457
458                 return binding<R>(
459                                 [self, func] { return func(self->get()); },
460                                 *this);
461         }
462
463         // Func -> R (T self_val, T2 other_val)
464         // Returns binding<R>
465         template<typename Func, typename T2>
466         auto composed(const binding<T2>& other, const Func& func) const -> binding<decltype(func(impl_->value_, other.impl_->value_))>
467         {
468                 typedef decltype(func(impl_->value_, other.impl_->value_)) R;
469                 auto self = impl_;
470                 auto o = other.impl_;
471
472                 return binding<R>(
473                                 [self, o, func] { return func(self->get(), o->get()); },
474                                 *this,
475                                 other);
476         }
477
478         template<typename TweenerFunc, typename FrameCounter>
479         binding<T> animated(
480                         const binding<FrameCounter>& frame_counter,
481                         const binding<FrameCounter>& duration,
482                         const binding<TweenerFunc>& tweener_func) const
483         {
484                 auto self                                       = impl_;
485                 auto f                                          = frame_counter.impl_;
486                 auto d                                          = duration.impl_;
487                 auto tw                                         = tweener_func.impl_;
488                 FrameCounter start_frame        = frame_counter.get();
489                 FrameCounter current_frame      = start_frame;
490                 T current_source                        = get();
491                 T current_destination           = current_source;
492                 T current_result                        = current_source;
493
494                 auto result = binding<T>(
495                         [=] () mutable
496                         {
497                                 auto frame_diff         = f->get() - current_frame;
498                                 bool new_frame          = f->get() != current_frame;
499
500                                 if (!new_frame)
501                                         return current_result;
502
503                                 bool new_tween          = current_destination != self->get();
504                                 auto time                       = current_frame - start_frame + (new_tween ? frame_diff : 0) + 1;
505                                 auto dur                        = d->get();
506                                 current_frame           = f->get();
507
508                                 current_source          = new_tween ? tw->get()(time, current_source, current_destination - current_source, dur) : current_source;
509                                 current_destination     = self->get();
510
511                                 if (new_tween)
512                                         start_frame             = current_frame;
513
514                                 time                            = current_frame - start_frame;
515
516                                 if (time < dur)
517                                         current_result = tw->get()(time, current_source, current_destination - current_source, dur);
518                                 else
519                                 {
520                                         current_result = current_destination;
521                                         current_source = current_destination;
522                                 }
523
524                                 return current_result;
525                         });
526
527                 result.depend_on(*this);
528                 result.depend_on(frame_counter);
529                 result.depend_on(tweener_func);
530
531                 return result;
532         }
533
534         void unbind()
535         {
536                 impl_->unbind();
537         }
538
539         void on_change(
540                         const std::weak_ptr<void>& dependant,
541                         const std::function<void ()>& listener) const
542         {
543                 impl_->on_change(dependant, listener);
544         }
545
546         std::shared_ptr<void> on_change(
547                         const std::function<void ()>& listener) const
548         {
549                 std::shared_ptr<void> subscription(new char);
550
551                 on_change(subscription, listener);
552
553                 return subscription;
554         }
555 private:
556         binding(const std::shared_ptr<impl>& self)
557                 : impl_(self)
558         {
559         }
560 };
561
562 static binding<bool> operator||(const binding<bool>& lhs, const binding<bool>& rhs)
563 {
564         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs || rhs; });
565 }
566
567 static binding<bool> operator||(const binding<bool>& lhs, bool rhs)
568 {
569         return lhs.transformed([rhs](bool lhs) { return lhs || rhs; });
570 }
571
572 static binding<bool> operator&&(const binding<bool>& lhs, const binding<bool>& rhs)
573 {
574         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs && rhs; });
575 }
576
577 static binding<bool> operator&&(const binding<bool>& lhs, bool rhs)
578 {
579         return lhs.transformed([rhs](bool lhs) { return lhs && rhs; });
580 }
581
582 static binding<bool> operator!(const binding<bool>& self)
583 {
584         return self.transformed([](bool self) { return !self; });
585 }
586
587 template<typename T>
588 class ternary_builder
589 {
590         binding<bool> condition_;
591         binding<T> true_result_;
592 public:
593         ternary_builder(
594                         const binding<bool>& condition, const binding<T>& true_result)
595                 : condition_(condition)
596                 , true_result_(true_result)
597         {
598         }
599
600         binding<T> otherwise(const binding<T>& false_result)
601         {
602                 auto condition = condition_;
603                 auto true_result = true_result_;
604
605                 binding<T> result([condition, true_result, false_result]()
606                 {
607                         return condition.get() ? true_result.get() : false_result.get();
608                 });
609
610                 result.depend_on(condition);
611                 result.depend_on(true_result);
612                 result.depend_on(false_result);
613
614                 return result;
615         }
616
617         binding<T> otherwise(T false_result)
618         {
619                 return otherwise(binding<T>(false_result));
620         }
621 };
622
623 class when
624 {
625         binding<bool> condition_;
626 public:
627         when(const binding<bool>& condition)
628                 : condition_(condition)
629         {
630         }
631
632         template<typename T>
633         ternary_builder<T> then(const binding<T>& true_result)
634         {
635                 return ternary_builder<T>(condition_, true_result);
636         }
637
638         template<typename T>
639         ternary_builder<T> then(T true_result)
640         {
641                 return then(binding<T>(true_result));
642         }
643 };
644
645 /*template<typename T, typename T2>
646 binding<T> add_tween(
647                 const binding<T>& to_tween,
648                 const binding<T2>& counter,
649                 T destination_value,
650                 T2 duration,
651                 const std::wstring& easing)
652 {
653         tweener tween(easing);
654
655         double start_val = to_tween.as<double>().get();
656         double destination_val = static_cast<double>(destination_value);
657         double start_time = counter.as<double>().get();
658         double dur = static_cast<double>(duration);
659
660         return when(counter < duration)
661                 .then(counter.as<double>().transformed([=](double t)
662                 {
663                         return tween(t - start_time, start_val, destination_val, dur);
664                 }).as<T>())
665                 .otherwise(destination_value);
666 }*/
667
668 template<typename T, typename T2>
669 binding<T> delay(
670                 const binding<T>& to_delay,
671                 const binding<T>& after_delay,
672                 const binding<T2>& counter,
673                 T2 duration)
674 {
675         return when(counter < duration)
676                         .then(to_delay)
677                         .otherwise(after_delay);
678 }
679
680 }}