]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: Added tweens for mixer animations.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 19 Mar 2011 19:23:56 +0000 (19:23 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 19 Mar 2011 19:23:56 +0000 (19:23 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@569 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

12 files changed:
common/compiler/vs/disable_silly_warnings.h
core/producer/frame/audio_transform.cpp
core/producer/frame/audio_transform.h
core/producer/frame/image_transform.cpp
core/producer/frame/image_transform.h
mixer/frame_mixer_device.cpp
mixer/frame_mixer_device.h
mixer/mixer.vcxproj
mixer/mixer.vcxproj.filters
mixer/tween.h [new file with mode: 0644]
protocol/amcp/AMCPCommandsImpl.cpp
shell/caspar.config

index 016f9dc88e86aa6022bfc01d39105798f9f8e0c2..a65c3d11babc2fd492d9f1f3670098855ed44987 100644 (file)
@@ -4,6 +4,7 @@
 #pragma warning (disable : 4482) // nonstandard extension used: enum 'enum' used in qualified name\r
 #pragma warning (disable : 4127) // conditional expression is constant\r
 #pragma warning (disable : 4714) // marked as __forceinline not inlined\r
-#pragma warning (disable : 4503) //  decorated name length exceeded, name was truncated\r
+#pragma warning (disable : 4503) // decorated name length exceeded, name was truncated\r
+#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored\r
 #endif\r
 \r
index 8ca5083a8f21921b14c6736143c1e92dee21a718..f046c5363dfe6ac3cf91391feb2c54ab8f65efb4 100644 (file)
@@ -40,16 +40,10 @@ const audio_transform audio_transform::operator*(const audio_transform &other) c
        return audio_transform(*this) *= other;\r
 }\r
 \r
-template<typename T>\r
-T mix(const T& lhs, const T& rhs, float alpha)\r
-{\r
-       return (1.0f - alpha) * lhs + alpha * rhs;\r
-}\r
-\r
-audio_transform lerp(const audio_transform& lhs, const audio_transform& rhs, float alpha)\r
+audio_transform tween(const audio_transform& lhs, const audio_transform& rhs, const std::function<double(double, double, double)>& tweener, float alpha)\r
 {\r
        audio_transform result;\r
-       result.set_gain(mix(lhs.get_gain(), rhs.get_gain(), alpha));\r
+       result.set_gain(tweener(lhs.get_gain(), rhs.get_gain(), alpha));\r
        result.set_has_audio(lhs.get_has_audio() || rhs.get_has_audio());\r
        return result;\r
 }\r
index 67afcf42d2d7bb8298645270868c01aa72d3ade8..035138a77eed75ea29ca41f92b7d7943b9286ef5 100644 (file)
@@ -20,6 +20,6 @@ private:
        bool audio_;\r
 };\r
 \r
-audio_transform lerp(const audio_transform& lhs, const audio_transform& rhs, float alpha);\r
+audio_transform tween(const audio_transform& lhs, const audio_transform& rhs, const std::function<double(double, double, double)>& tweener, float alpha);\r
 \r
 }}
\ No newline at end of file
index d07c5d05c39e0926bcafb58c40be9ddb3f8d8710..d1b7afce7970d5851fb97ba0d291613ed44c7ba7 100644 (file)
@@ -113,24 +113,18 @@ const image_transform image_transform::operator*(const image_transform &other) c
        return image_transform(*this) *= other;\r
 }\r
 \r
-template<typename T>\r
-T mix(const T& lhs, const T& rhs, float alpha)\r
-{\r
-       return (1.0f - alpha) * lhs + alpha * rhs;\r
-}\r
-\r
-image_transform lerp(const image_transform& lhs, const image_transform& rhs, float alpha)\r
+image_transform tween(const image_transform& lhs, const image_transform& rhs, const std::function<double(double, double, double)>& tweener, float alpha)\r
 {\r
        CASPAR_ASSERT(lhs.get_mode() == rhs.get_mode() || lhs.get_mode() == video_mode::invalid || rhs.get_mode() == video_mode::invalid);\r
 \r
        image_transform result; \r
        result.set_mode(rhs.get_mode() != video_mode::invalid ? rhs.get_mode() : lhs.get_mode());\r
-       result.set_gain(mix(lhs.get_gain(), rhs.get_gain(), alpha));\r
-       result.set_opacity(mix(lhs.get_opacity(), rhs.get_opacity(), alpha));\r
-       result.set_fill_translation(mix(lhs.get_fill_translation()[0], rhs.get_fill_translation()[0], alpha), mix(lhs.get_fill_translation()[1], rhs.get_fill_translation()[1], alpha));\r
-       result.set_fill_scale(mix(lhs.get_fill_scale()[0], rhs.get_fill_scale()[0], alpha), mix(lhs.get_fill_scale()[1], rhs.get_fill_scale()[1], alpha));\r
-       result.set_key_translation(mix(lhs.get_key_translation()[0], rhs.get_key_translation()[0], alpha), mix(lhs.get_key_translation()[1], rhs.get_key_translation()[1], alpha));\r
-       result.set_key_scale(mix(lhs.get_key_scale()[0], rhs.get_key_scale()[0], alpha), mix(lhs.get_key_scale()[1], rhs.get_key_scale()[1], alpha));\r
+       result.set_gain(tweener(lhs.get_gain(), rhs.get_gain(), alpha));\r
+       result.set_opacity(tweener(lhs.get_opacity(), rhs.get_opacity(), alpha));\r
+       result.set_fill_translation(tweener(lhs.get_fill_translation()[0], rhs.get_fill_translation()[0], alpha), tweener(lhs.get_fill_translation()[1], rhs.get_fill_translation()[1], alpha));\r
+       result.set_fill_scale(tweener(lhs.get_fill_scale()[0], rhs.get_fill_scale()[0], alpha), tweener(lhs.get_fill_scale()[1], rhs.get_fill_scale()[1], alpha));\r
+       result.set_key_translation(tweener(lhs.get_key_translation()[0], rhs.get_key_translation()[0], alpha), tweener(lhs.get_key_translation()[1], rhs.get_key_translation()[1], alpha));\r
+       result.set_key_scale(tweener(lhs.get_key_scale()[0], rhs.get_key_scale()[0], alpha), tweener(lhs.get_key_scale()[1], rhs.get_key_scale()[1], alpha));\r
        \r
        return result;\r
 }\r
index e48f3fc79e4eedbc7b5ed0ddd2734382e8aba63a..d872ad9a3720284ec8c219949fab79fc11b4ec10 100644 (file)
@@ -46,7 +46,7 @@ private:
        video_mode::type mode_;\r
 };\r
 \r
-image_transform lerp(const image_transform& lhs, const image_transform& rhs, float alpha);\r
+image_transform tween(const image_transform& lhs, const image_transform& rhs, const std::function<double(double, double, double)>& tweener, float alpha);\r
 \r
 inline bool operator==(const image_transform& lhs, const image_transform& rhs)\r
 {\r
index 3ee61027ac0494db89574119675e18d88702d03f..bcc0e77c37e2da7a045f5086d02648e75ad93c54 100644 (file)
@@ -8,6 +8,7 @@
 #include <core/producer/frame/audio_transform.h>\r
 #include <core/producer/frame/image_transform.h>\r
 \r
+#include "tween.h"\r
 #include "audio/audio_mixer.h"\r
 #include "image/image_mixer.h"\r
 \r
 namespace caspar { namespace core {\r
                \r
 template<typename T>\r
-class basic_animated_value\r
+class tweened_transform\r
 {\r
        T source_;\r
        T dest_;\r
        int duration_;\r
        int time_;\r
+       std::wstring tween_;\r
 public:        \r
-       basic_animated_value()\r
+       tweened_transform()\r
                : duration_(0)\r
-               , time_(0){}\r
-       basic_animated_value(const T& source, const T& dest, int duration)\r
+               , time_(0)\r
+               , tween_(L"linear"){}\r
+       tweened_transform(const T& source, const T& dest, int duration, const std::wstring& tween = L"linear")\r
                : source_(source)\r
                , dest_(dest)\r
                , duration_(duration)\r
-               , time_(0){}\r
+               , time_(0)\r
+               , tween_(tween){}\r
        \r
        virtual T fetch()\r
        {\r
-               return lerp(source_, dest_, duration_ < 1 ? 1.0f : static_cast<float>(time_)/static_cast<float>(duration_));\r
+               return tween(source_, dest_, std::bind(&caspar::tween<double>, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, tween_), duration_ < 1 ? 1.0f : static_cast<float>(time_)/static_cast<float>(duration_));\r
        }\r
        virtual T fetch_and_tick(int num)\r
        {                                               \r
@@ -65,11 +69,11 @@ struct frame_mixer_device::implementation : boost::noncopyable
 \r
        output_t output_;\r
 \r
-       std::unordered_map<int, basic_animated_value<image_transform>> image_transforms_;\r
-       std::unordered_map<int, basic_animated_value<audio_transform>> audio_transforms_;\r
+       std::unordered_map<int, tweened_transform<image_transform>> image_transforms_;\r
+       std::unordered_map<int, tweened_transform<audio_transform>> audio_transforms_;\r
 \r
-       basic_animated_value<image_transform> root_image_transform_;\r
-       basic_animated_value<audio_transform> root_audio_transform_;\r
+       tweened_transform<image_transform> root_image_transform_;\r
+       tweened_transform<audio_transform> root_audio_transform_;\r
 \r
        executor executor_;\r
 public:\r
@@ -165,103 +169,103 @@ public:
                return make_safe<gpu_write_frame>(desc, image_mixer_.create_buffers(desc));\r
        }\r
                                \r
-       void set_image_transform(const image_transform& transform, int mix_duration)\r
+       void set_image_transform(const image_transform& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = root_image_transform_.fetch();\r
                        auto dst = transform;\r
-                       root_image_transform_ = basic_animated_value<image_transform>(src, dst, mix_duration);\r
+                       root_image_transform_ = tweened_transform<image_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void set_audio_transform(const audio_transform& transform, int mix_duration)\r
+       void set_audio_transform(const audio_transform& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = root_audio_transform_.fetch();\r
                        auto dst = transform;\r
-                       root_audio_transform_ = basic_animated_value<audio_transform>(src, dst, mix_duration);\r
+                       root_audio_transform_ = tweened_transform<audio_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void set_image_transform(int index, const image_transform& transform, int mix_duration)\r
+       void set_image_transform(int index, const image_transform& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = image_transforms_[index].fetch();\r
                        auto dst = transform;\r
-                       image_transforms_[index] = basic_animated_value<image_transform>(src, dst, mix_duration);\r
+                       image_transforms_[index] = tweened_transform<image_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void set_audio_transform(int index, const audio_transform& transform, int mix_duration)\r
+       void set_audio_transform(int index, const audio_transform& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = audio_transforms_[index].fetch();\r
                        auto dst = transform;\r
-                       audio_transforms_[index] = basic_animated_value<audio_transform>(src, dst, mix_duration);\r
+                       audio_transforms_[index] = tweened_transform<audio_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
        \r
-       void apply_image_transform(const std::function<image_transform(const image_transform&)>& transform, int mix_duration)\r
+       void apply_image_transform(const std::function<image_transform(const image_transform&)>& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                return executor_.invoke([&]\r
                {\r
                        auto src = root_image_transform_.fetch();\r
                        auto dst = transform(src);\r
-                       root_image_transform_ = basic_animated_value<image_transform>(src, dst, mix_duration);\r
+                       root_image_transform_ = tweened_transform<image_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration)\r
+       void apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                return executor_.invoke([&]\r
                {\r
                        auto src = root_audio_transform_.fetch();\r
                        auto dst = transform(src);\r
-                       root_audio_transform_ = basic_animated_value<audio_transform>(src, dst, mix_duration);\r
+                       root_audio_transform_ = tweened_transform<audio_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration)\r
+       void apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = image_transforms_[index].fetch();\r
                        auto dst = transform(src);\r
-                       image_transforms_[index] = basic_animated_value<image_transform>(src, dst, mix_duration);\r
+                       image_transforms_[index] = tweened_transform<image_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration)\r
+       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        auto src = audio_transforms_[index].fetch();\r
                        auto dst = transform(src);\r
-                       audio_transforms_[index] = basic_animated_value<audio_transform>(src, dst, mix_duration);\r
+                       audio_transforms_[index] = tweened_transform<audio_transform>(src, dst, mix_duration, tween);\r
                });\r
        }\r
 \r
-       void reset_image_transform(int mix_duration)\r
+       void reset_image_transform(int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        BOOST_FOREACH(auto& t, image_transforms_)                       \r
-                                t.second = basic_animated_value<image_transform>(t.second.fetch(), image_transform(), mix_duration);                   \r
-                       root_image_transform_ = basic_animated_value<image_transform>(root_image_transform_.fetch(), image_transform(), mix_duration);\r
+                                t.second = tweened_transform<image_transform>(t.second.fetch(), image_transform(), mix_duration, tween);                       \r
+                       root_image_transform_ = tweened_transform<image_transform>(root_image_transform_.fetch(), image_transform(), mix_duration, tween);\r
                });\r
        }\r
 \r
-       void reset_audio_transform(int mix_duration)\r
+       void reset_audio_transform(int mix_duration, const std::wstring& tween)\r
        {\r
                executor_.invoke([&]\r
                {\r
                        BOOST_FOREACH(auto& t, audio_transforms_)\r
-                               t.second = basic_animated_value<audio_transform>(t.second.fetch(), audio_transform(), mix_duration);\r
-                       root_audio_transform_ = basic_animated_value<audio_transform>(root_audio_transform_.fetch(), audio_transform(), mix_duration);\r
+                               t.second = tweened_transform<audio_transform>(t.second.fetch(), audio_transform(), mix_duration, tween);\r
+                       root_audio_transform_ = tweened_transform<audio_transform>(root_audio_transform_.fetch(), audio_transform(), mix_duration, tween);\r
                });\r
        }\r
 \r
@@ -294,15 +298,15 @@ safe_ptr<write_frame> frame_mixer_device::create_frame(pixel_format::type pix_fm
        desc.planes.push_back(pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4));\r
        return create_frame(desc);\r
 }\r
-void frame_mixer_device::set_image_transform(const image_transform& transform, int mix_duration){impl_->set_image_transform(transform, mix_duration);}\r
-void frame_mixer_device::set_image_transform(int index, const image_transform& transform, int mix_duration){impl_->set_image_transform(index, transform, mix_duration);}\r
-void frame_mixer_device::set_audio_transform(const audio_transform& transform, int mix_duration){impl_->set_audio_transform(transform, mix_duration);}\r
-void frame_mixer_device::set_audio_transform(int index, const audio_transform& transform, int mix_duration){impl_->set_audio_transform(index, transform, mix_duration);}\r
-void frame_mixer_device::apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration ){impl_->apply_image_transform(transform, mix_duration);}\r
-void frame_mixer_device::apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration){impl_->apply_image_transform(index, transform, mix_duration);}\r
-void frame_mixer_device::apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration){impl_->apply_audio_transform(transform, mix_duration);}\r
-void frame_mixer_device::apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration ){impl_->apply_audio_transform(index, transform, mix_duration);}\r
-void frame_mixer_device::reset_image_transform(int mix_duration){impl_->reset_image_transform(mix_duration);}\r
-void frame_mixer_device::reset_audio_transform(int mix_duration){impl_->reset_audio_transform(mix_duration);}\r
+void frame_mixer_device::set_image_transform(const image_transform& transform, int mix_duration, const std::wstring& tween){impl_->set_image_transform(transform, mix_duration, tween);}\r
+void frame_mixer_device::set_image_transform(int index, const image_transform& transform, int mix_duration, const std::wstring& tween){impl_->set_image_transform(index, transform, mix_duration, tween);}\r
+void frame_mixer_device::set_audio_transform(const audio_transform& transform, int mix_duration, const std::wstring& tween){impl_->set_audio_transform(transform, mix_duration, tween);}\r
+void frame_mixer_device::set_audio_transform(int index, const audio_transform& transform, int mix_duration, const std::wstring& tween){impl_->set_audio_transform(index, transform, mix_duration, tween);}\r
+void frame_mixer_device::apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration, const std::wstring& tween){impl_->apply_image_transform(transform, mix_duration, tween);}\r
+void frame_mixer_device::apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration, const std::wstring& tween){impl_->apply_image_transform(index, transform, mix_duration, tween);}\r
+void frame_mixer_device::apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration, const std::wstring& tween){impl_->apply_audio_transform(transform, mix_duration, tween);}\r
+void frame_mixer_device::apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration, const std::wstring& tween){impl_->apply_audio_transform(index, transform, mix_duration, tween);}\r
+void frame_mixer_device::reset_image_transform(int mix_duration, const std::wstring& tween){impl_->reset_image_transform(mix_duration, tween);}\r
+void frame_mixer_device::reset_audio_transform(int mix_duration, const std::wstring& tween){impl_->reset_audio_transform(mix_duration, tween);}\r
 \r
 }}
\ No newline at end of file
index 68a7213b7d0a1763b17c52dd593ee97a64cf7c17..295091da4e344d97d5aba97703c8b14af51a2ebd 100644 (file)
@@ -56,20 +56,20 @@ public:
        \r
        const video_format_desc& get_video_format_desc() const; // nothrow\r
 \r
-       void set_image_transform(const image_transform& transform, int mix_duration = 0);\r
-       void set_image_transform(int index, const image_transform& transform, int mix_duration = 0);\r
+       void set_image_transform(const image_transform& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void set_image_transform(int index, const image_transform& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
 \r
-       void set_audio_transform(const audio_transform& transform, int mix_duration = 0);\r
-       void set_audio_transform(int index, const audio_transform& transform, int mix_duration = 0);\r
+       void set_audio_transform(const audio_transform& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void set_audio_transform(int index, const audio_transform& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
        \r
-       void apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration = 0);\r
-       void apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration = 0);\r
+       void apply_image_transform(const std::function<image_transform(image_transform)>& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void apply_image_transform(int index, const std::function<image_transform(image_transform)>& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
 \r
-       void apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0);\r
-       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0);\r
+       void apply_audio_transform(const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void apply_audio_transform(int index, const std::function<audio_transform(audio_transform)>& transform, int mix_duration = 0, const std::wstring& tween = L"linear");\r
 \r
-       void reset_image_transform(int mix_duration = 0);\r
-       void reset_audio_transform(int mix_duration = 0);\r
+       void reset_image_transform(int mix_duration = 0, const std::wstring& tween = L"linear");\r
+       void reset_audio_transform(int mix_duration = 0, const std::wstring& tween = L"linear");\r
 \r
 private:\r
        struct implementation;\r
index 59e6251059f8fe6a715e6785913719fc58c4e726..1385d61e36ec1b3cf6a0b0628a9b6ed65eaad390 100644 (file)
@@ -86,6 +86,7 @@
     <ClInclude Include="image\image_kernel.h" />\r
     <ClInclude Include="image\image_mixer.h" />\r
     <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="tween.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ProjectReference Include="..\common\common.vcxproj">\r
index 69ea9fc8aad0638998a7160ed559e56cdc066fdc..68bfd02384f7aa587c4925873c2d6060db556bee 100644 (file)
@@ -66,5 +66,6 @@
     <ClInclude Include="gpu\gpu_read_frame.h">\r
       <Filter>gpu</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="tween.h" />\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/mixer/tween.h b/mixer/tween.h
new file mode 100644 (file)
index 0000000..4556264
--- /dev/null
@@ -0,0 +1,95 @@
+#pragma once\r
+\r
+#include <boost/assign/list_of.hpp>\r
+#include <unordered_map>\r
+#include <string>\r
+#include <locale>\r
+\r
+namespace caspar {\r
+                       \r
+static const double PI = std::atan(1.0)*4.0;\r
+static const double H_PI = std::atan(1.0)*2.0;\r
+\r
+template<typename T>\r
+inline T ease_none(T b, T e, T d) \r
+{\r
+       return b + (e-b)*d;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_in_sine(T b, T e, T d)  \r
+{\r
+       return -(e-b) * std::cos(d * H_PI) + (e-b) + b;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_out_sine(T b, T e, T d)  \r
+{ \r
+       return (e-b) * std::sin(d * H_PI) + b;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_in_out_sine(T b, T e, T d)  \r
+{ \r
+       return -(e-b)/2 * (std::cos(PI*d) - 1.0) + b;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_out_in_sine(T b, T e, T d)  \r
+{\r
+       return d < 0.5 ? ease_out_sine(b, e+(e-b)*0.5, d*2.0) : ease_out_sine(b+(e-b)*0.5, e, d*2.0-1.0);\r
+}\r
+\r
+template<typename T>\r
+inline T ease_in_cubic(T b, T e, T d)  \r
+{ \r
+       return (e-b) * std::pow(d, 3) + b;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_out_cubic(T b, T e, T d)  \r
+{ \r
+       return (e-b) * (std::pow(d-1.0, 3)+1.0) + b;\r
+}\r
+       \r
+template<typename T>\r
+inline T ease_in_out_cubic(T b, T e, T d)  \r
+{ \r
+       return d < 0.5 ? (e-b)*0.5 * std::pow(d*2.0, 3) + b : (e-b)*0.5 * (std::pow(d*2.0-2.0, 3)+2.0)+ b;\r
+}\r
+\r
+template<typename T>\r
+inline T ease_out_in_cubic(T b, T e, T d)  \r
+{ \r
+       return d < 0.5 ? ease_out_cubic(b, e+(e-b)*0.5, d*2.0) : ease_in_cubic(b+(e-b)*0.5, e, d*2.0-1.0);\r
+}\r
+\r
+template<typename T>\r
+inline T tween(T b, T e, T d, std::wstring name = L"linear")\r
+{\r
+       std::transform(name.begin(), name.end(), name.begin(), std::tolower);\r
+\r
+       typedef std::function<T(T,T,T)> tween_func;\r
+       static std::unordered_map<std::wstring, tween_func> tweens = boost::assign::map_list_of\r
+               (L"linear", ease_none<T>)\r
+               (L"easenone", ease_none<T>)\r
+               (L"easeinsine", ease_in_sine<T>)\r
+               (L"easeoutsine", ease_out_sine<T>)\r
+               (L"easeinoutsine", ease_in_out_sine<T>)\r
+               (L"easeoutinsine", ease_out_in_sine<T>)\r
+               (L"easeincubic", ease_in_cubic<T>)\r
+               (L"easeoutcubic", ease_out_cubic<T>)\r
+               (L"easeinoutcubic", ease_in_out_cubic<T>)\r
+               (L"easeoutincubic", ease_out_in_cubic<T>);\r
+\r
+       auto it = tweens.find(name);\r
+       if(it == tweens.end())\r
+       {\r
+               CASPAR_LOG(warning) << L" Invalid tween: " << name << L" fallback to \"linear\".";\r
+               return ease_none(b, e, d);\r
+       }\r
+\r
+       return it->second(b, e, d);\r
+};\r
+\r
+}
\ No newline at end of file
index 525f8ddd99a979196c745b59242d572f44954ea0..abe8dac7adb05cae1523fd8347cffd3fc2b586d6 100644 (file)
@@ -179,6 +179,8 @@ bool MixerCommand::DoExecute()
                        if(_parameters[1] == L"OPACITY")\r
                        {\r
                                int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
+\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
                        \r
                                auto transform = [=](image_transform transform) -> image_transform\r
@@ -189,13 +191,14 @@ bool MixerCommand::DoExecute()
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())                                    \r
-                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration, tween);\r
                                else\r
-                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration, tween);\r
                        }\r
                        else if(_parameters[1] == L"GAIN")\r
                        {\r
                                int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
                                double value = boost::lexical_cast<double>(_parameters.at(2));\r
                                \r
                                auto transform = [=](image_transform transform) -> image_transform\r
@@ -206,13 +209,14 @@ bool MixerCommand::DoExecute()
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration, tween);\r
                                else\r
-                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration, tween);\r
                        }\r
                        else if(_parameters[1] == L"FILL_RECT")\r
                        {\r
                                int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear";\r
                                double x        = boost::lexical_cast<double>(_parameters.at(2));\r
                                double y        = boost::lexical_cast<double>(_parameters.at(3));\r
                                double x_s      = boost::lexical_cast<double>(_parameters.at(4));\r
@@ -229,13 +233,14 @@ bool MixerCommand::DoExecute()
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration, tween);\r
                                else\r
-                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration, tween);\r
                        }\r
                        else if(_parameters[1] == L"KEY_RECT")\r
                        {\r
                                int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear";\r
                                double x        = boost::lexical_cast<double>(_parameters.at(2));\r
                                double y        = boost::lexical_cast<double>(_parameters.at(3));\r
                                double x_s      = boost::lexical_cast<double>(_parameters.at(4));\r
@@ -250,12 +255,14 @@ bool MixerCommand::DoExecute()
 \r
                                int layer = GetLayerIndex(std::numeric_limits<int>::min());\r
                                if(layer != std::numeric_limits<int>::min())\r
-                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(GetLayerIndex(), transform, duration, tween);\r
                                else\r
-                                       GetChannel()->mixer().apply_image_transform(transform, duration);\r
+                                       GetChannel()->mixer().apply_image_transform(transform, duration, tween);\r
                        }\r
                        else if(_parameters[1] == L"GRID")\r
                        {\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
                                int n = boost::lexical_cast<int>(_parameters.at(2));\r
                                double delta = 1.0/static_cast<double>(n);\r
                                for(int x = 0; x < n; ++x)\r
@@ -271,7 +278,7 @@ bool MixerCommand::DoExecute()
                                                        transform.set_key_scale(delta, delta);\r
                                                        return transform;\r
                                                };\r
-                                               GetChannel()->mixer().apply_image_transform(index, transform, 0);\r
+                                               GetChannel()->mixer().apply_image_transform(index, transform, duration, tween);\r
                                        }\r
                                }\r
                        }\r
index b518723582a00351950636de759cdaf1279e36ce..de9ae38b4611d2ec62ed41c2503d73a4b26d1d64 100644 (file)
@@ -19,7 +19,7 @@
           <stretch>uniform</stretch>\r
           <windowed>true</windowed>\r
         </ogl>\r
-        <audio/>\r
+        <!--<audio/>-->\r
         <!--decklink>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r