]> git.sesse.net Git - casparcg/blob - core/producer/scene/scene_producer.h
* Merged MIXER CROP, MIXER ANCHOR, MIXER ROTATION and MIXER PERSPECTIVE from 2.0
[casparcg] / core / producer / scene / scene_producer.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 <common/log.h>
25
26 #include "../frame_producer.h"
27
28 #include "../binding.h"
29 #include "../variable.h"
30
31 namespace caspar { namespace core {
32
33 class frame_factory;
34
35 namespace scene {
36
37 struct coord
38 {
39         binding<double> x;
40         binding<double> y;
41 };
42
43 struct rect
44 {
45         coord upper_left;
46         coord lower_right;
47 };
48
49 struct corners
50 {
51         coord upper_left;
52         coord upper_right;
53         coord lower_right;
54         coord lower_left;
55 };
56
57 struct adjustments
58 {
59         binding<double> opacity;
60
61         adjustments();
62 };
63
64 struct layer
65 {
66         binding<std::wstring>                                           name;
67         scene::coord                                                            anchor;
68         scene::coord                                                            position;
69         scene::rect                                                                     crop;
70         scene::corners                                                          perspective;
71         binding<double>                                                         rotation;
72         scene::adjustments                                                      adjustments;
73         binding<spl::shared_ptr<frame_producer>>        producer;
74         binding<bool>                                                           hidden;
75         binding<bool>                                                           is_key;
76
77         explicit layer(const std::wstring& name, const spl::shared_ptr<frame_producer>& producer);
78 };
79
80 struct keyframe
81 {
82         std::function<void ()>                                                                                          on_start_animate;
83         std::function<void (int64_t start_frame, int64_t current_frame)>        on_animate_to;
84         std::function<void ()>                                                                                          on_destination_frame;
85         int64_t                                                                                                                         destination_frame;
86 public:
87         keyframe(int64_t destination_frame)
88                 : destination_frame(destination_frame)
89         {
90         }
91 };
92
93 class scene_producer : public frame_producer_base
94 {
95 public:
96         scene_producer(int width, int height);
97         ~scene_producer();
98
99         class draw_frame receive_impl() override;
100         constraints& pixel_constraints() override;
101         void on_interaction(const interaction_event::ptr& event) override;
102         bool collides(double x, double y) const override;
103         std::wstring print() const override;
104         std::wstring name() const override;
105         std::future<std::wstring>       call(const std::vector<std::wstring>& params) override;
106         boost::property_tree::wptree info() const override;
107         monitor::subject& monitor_output();
108
109         layer& create_layer(
110                         const spl::shared_ptr<frame_producer>& producer, int x, int y, const std::wstring& name);
111         layer& create_layer(
112                         const spl::shared_ptr<frame_producer>& producer, const std::wstring& name);
113         binding<int64_t> frame();
114         binding<double> speed();
115
116         template<typename T> binding<T>& create_variable(
117                         const std::wstring& name, bool is_public, const std::wstring& expr = L"")
118         {
119                 std::shared_ptr<core::variable> var =
120                                 std::make_shared<core::variable_impl<T>>(expr, is_public);
121
122                 store_variable(name, var);
123
124                 return var->as<T>();
125         }
126
127         template<typename T>
128         void add_keyframe(
129                         binding<T>& to_affect,
130                         T destination_value,
131                         int64_t at_frame,
132                         const std::wstring& easing)
133         {
134                 add_keyframe(to_affect, binding<T>(destination_value), at_frame, easing);
135         }
136
137         template<typename T>
138         void add_keyframe(
139                         binding<T>& to_affect,
140                         const binding<T>& destination_value,
141                         int64_t at_frame,
142                         const std::wstring& easing)
143         {
144                 if (easing.empty())
145                 {
146                         add_keyframe(to_affect, destination_value, at_frame);
147                         return;
148                 }
149
150                 tweener tween(easing);
151                 keyframe k(at_frame);
152
153                 std::shared_ptr<T> start_value(new T);
154
155                 k.on_start_animate = [=]() mutable
156                 {
157                         *start_value = to_affect.get();
158                         to_affect.unbind();
159                 };
160
161                 k.on_destination_frame = [=]() mutable
162                 {
163                         to_affect.bind(destination_value);
164                 };
165
166                 k.on_animate_to =
167                                 [=](int64_t start_frame, int64_t current_frame) mutable
168                                 {
169                                         auto relative_frame = current_frame - start_frame;
170                                         auto duration = at_frame - start_frame;
171                                         auto tweened = static_cast<T>(tween(
172                                                         static_cast<double>(relative_frame),
173                                                         *start_value,
174                                                         destination_value.get() - *start_value,
175                                                         static_cast<double>(duration)));
176
177                                         to_affect.set(tweened);
178                                         
179                                         //CASPAR_LOG(info) << relative_frame << L" " << *start_value << L" " << duration << L" " << tweened;
180                                 };
181
182                 store_keyframe(to_affect.identity(), k);
183         }
184
185         template<typename T>
186         void add_keyframe(binding<T>& to_affect, T set_value, int64_t at_frame)
187         {
188                 add_keyframe(to_affect, binding<T>(set_value), at_frame);
189         }
190
191         template<typename T>
192         void add_keyframe(binding<T>& to_affect, const binding<T>& set_value, int64_t at_frame)
193         {
194                 keyframe k(at_frame);
195
196                 k.on_destination_frame = [=]() mutable
197                 {
198                         to_affect.bind(set_value);
199                 };
200
201                 store_keyframe(to_affect.identity(), k);
202         }
203
204         core::variable& get_variable(const std::wstring& name) override;
205         const std::vector<std::wstring>& get_variables() const override;
206 private:
207         void store_keyframe(void* timeline_identity, const keyframe& k);
208         void store_variable(
209                         const std::wstring& name, const std::shared_ptr<core::variable>& var);
210
211         struct impl;
212         std::unique_ptr<impl> impl_;
213 };
214
215 spl::shared_ptr<frame_producer> create_dummy_scene_producer(const spl::shared_ptr<frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params);
216
217 }}}