]> git.sesse.net Git - casparcg/blobdiff - core/producer/scene/scene_producer.h
Fixed bug with monitor subject lifetime
[casparcg] / core / producer / scene / scene_producer.h
index c60f9a8b5705aaf4aa6197aab52f823da1495ef9..32e8e2c3102575704c8fa91aed78663adffded1f 100644 (file)
 
 #pragma once
 
+#include <common/log.h>
+
 #include "../frame_producer.h"
 
 #include "../binding.h"
+#include "../variable.h"
+
+namespace caspar { namespace core {
+
+class frame_factory;
 
-namespace caspar { namespace core { namespace scene {
+namespace scene {
 
 struct coord
 {
@@ -33,6 +40,13 @@ struct coord
        binding<double> y;
 };
 
+struct rect
+{
+       coord upper_left;
+       binding<double> width;
+       binding<double> height;
+};
+
 struct adjustments
 {
        binding<double> opacity;
@@ -44,51 +58,25 @@ struct layer
 {
        binding<std::wstring> name;
        coord position;
+       rect clipping;
        adjustments adjustments;
        binding<spl::shared_ptr<frame_producer>> producer;
        binding<bool> hidden;
        binding<bool> is_key;
 
-       explicit layer(const spl::shared_ptr<frame_producer>& producer);
-       layer(const std::wstring& name, const spl::shared_ptr<frame_producer>& producer);
+       explicit layer(const std::wstring& name, const spl::shared_ptr<frame_producer>& producer);
 };
 
-template<typename T> class parameter_holder;
-
-class parameter_holder_base
+struct keyframe
 {
+       std::function<void ()> on_start_animate;
+       std::function<void (int64_t start_frame, int64_t current_frame)> on_animate_to;
+       std::function<void ()> on_destination_frame;
+       int64_t destination_frame;
 public:
-       virtual ~parameter_holder_base()
-       {
-       }
-
-       virtual void set(const std::wstring& raw_value) = 0;
-
-       template<typename T>
-       binding<T>& value()
-       {
-               return dynamic_cast<parameter_holder<T>>(*this).value();
-       }
-};
-
-template<typename T>
-class parameter_holder : public parameter_holder_base
-{
-       binding<T> value_;
-public:
-       parameter_holder(T initial_value)
-               : value_(initial_value)
-       {
-       }
-
-       binding<T>& value()
-       {
-               return value_;
-       }
-
-       virtual void set(const std::wstring& raw_value)
+       keyframe(int64_t destination_frame)
+               : destination_frame(destination_frame)
        {
-               value_.set(boost::lexical_cast<T>(raw_value));
        }
 };
 
@@ -106,32 +94,114 @@ public:
        std::wstring name() const override;
        boost::unique_future<std::wstring>      call(const std::vector<std::wstring>& params) override;
        boost::property_tree::wptree info() const override;
-       void subscribe(const monitor::observable::observer_ptr& o) override;
-       void unsubscribe(const monitor::observable::observer_ptr& o) override;
-       layer& create_layer(
-                       const spl::shared_ptr<frame_producer>& producer, int x, int y);
+       monitor::source& monitor_output();
+
        layer& create_layer(
                        const spl::shared_ptr<frame_producer>& producer, int x, int y, const std::wstring& name);
-       layer& create_layer(const spl::shared_ptr<frame_producer>& producer);
+       layer& create_layer(
+                       const spl::shared_ptr<frame_producer>& producer, const std::wstring& name);
        binding<int64_t> frame();
+       binding<double> speed();
 
-       template<typename T> binding<T>& create_parameter(const std::wstring& name, T initial_value = T())
+       template<typename T> binding<T>& create_variable(
+                       const std::wstring& name, bool is_public, const std::wstring& expr = L"")
        {
-               auto param = std::make_shared<parameter_holder<T>>(initial_value);
+               std::shared_ptr<core::variable> var =
+                               std::make_shared<core::variable_impl<T>>(expr, is_public);
+
+               store_variable(name, var);
+
+               return var->as<T>();
+       }
 
-               store_parameter(name, param);
+       template<typename T>
+       void add_keyframe(
+                       binding<T>& to_affect,
+                       T destination_value,
+                       int64_t at_frame,
+                       const std::wstring& easing)
+       {
+               add_keyframe(to_affect, binding<T>(destination_value), at_frame, easing);
+       }
 
-               return param->value();
+       template<typename T>
+       void add_keyframe(
+                       binding<T>& to_affect,
+                       const binding<T>& destination_value,
+                       int64_t at_frame,
+                       const std::wstring& easing)
+       {
+               if (easing.empty())
+               {
+                       add_keyframe(to_affect, destination_value, at_frame);
+                       return;
+               }
+
+               tweener tween(easing);
+               keyframe k(at_frame);
+
+               std::shared_ptr<T> start_value(new T);
+
+               k.on_start_animate = [=]() mutable
+               {
+                       *start_value = to_affect.get();
+                       to_affect.unbind();
+               };
+
+               k.on_destination_frame = [=]() mutable
+               {
+                       to_affect.bind(destination_value);
+               };
+
+               k.on_animate_to =
+                               [=](int64_t start_frame, int64_t current_frame) mutable
+                               {
+                                       auto relative_frame = current_frame - start_frame;
+                                       auto duration = at_frame - start_frame;
+                                       auto tweened = static_cast<T>(tween(
+                                                       static_cast<double>(relative_frame),
+                                                       *start_value,
+                                                       destination_value.get() - *start_value,
+                                                       static_cast<double>(duration)));
+
+                                       to_affect.set(tweened);
+                                       
+                                       //CASPAR_LOG(info) << relative_frame << L" " << *start_value << L" " << duration << L" " << tweened;
+                               };
+
+               store_keyframe(to_affect.identity(), k);
        }
+
+       template<typename T>
+       void add_keyframe(binding<T>& to_affect, T set_value, int64_t at_frame)
+       {
+               add_keyframe(to_affect, binding<T>(set_value), at_frame);
+       }
+
+       template<typename T>
+       void add_keyframe(binding<T>& to_affect, const binding<T>& set_value, int64_t at_frame)
+       {
+               keyframe k(at_frame);
+
+               k.on_destination_frame = [=]() mutable
+               {
+                       to_affect.bind(set_value);
+               };
+
+               store_keyframe(to_affect.identity(), k);
+       }
+
+       core::variable& get_variable(const std::wstring& name) override;
+       const std::vector<std::wstring>& get_variables() const override;
 private:
-       void store_parameter(
-                       const std::wstring& name,
-                       const std::shared_ptr<parameter_holder_base>& param);
+       void store_keyframe(void* timeline_identity, const keyframe& k);
+       void store_variable(
+                       const std::wstring& name, const std::shared_ptr<core::variable>& var);
 
        struct impl;
        std::unique_ptr<impl> impl_;
 };
 
-spl::shared_ptr<frame_producer> create_dummy_scene_producer(const spl::shared_ptr<class frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params);
+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);
 
 }}}