namespace caspar { namespace core {
-template <typename T>
-class binding
+namespace detail {
+
+struct impl_base : std::enable_shared_from_this<impl_base>
{
-private:
- struct impl_base : std::enable_shared_from_this<impl_base>
+ std::vector<std::shared_ptr<impl_base>> dependencies_;
+ mutable std::vector<std::pair<
+ std::weak_ptr<void>,
+ std::function<void ()>>> on_change_;
+
+ virtual ~impl_base()
{
- std::vector<std::shared_ptr<impl_base>> dependencies_;
- mutable std::vector<std::pair<
- std::weak_ptr<void>,
- std::function<void ()>>> on_change_;
+ }
- virtual ~impl_base()
- {
- }
+ virtual void evaluate() = 0;
- virtual void evaluate() = 0;
+ void depend_on(const std::shared_ptr<impl_base>& dependency)
+ {
+ dependency->on_change(shared_from_this(), [=] { evaluate(); });
+ dependencies_.push_back(dependency);
+ }
- void depend_on(const std::shared_ptr<impl_base>& dependency)
- {
- dependency->on_change(shared_from_this(), [=] { evaluate(); });
- dependencies_.push_back(dependency);
- }
+ void on_change(
+ const std::weak_ptr<void>& dependant,
+ const std::function<void ()>& listener) const
+ {
+ on_change_.push_back(std::make_pair(dependant, listener));
+ }
+};
- void on_change(
- const std::weak_ptr<void>& dependant,
- const std::function<void ()>& listener) const
- {
- on_change_.push_back(std::make_pair(dependant, listener));
- }
- };
+}
- struct impl : public impl_base
+template <typename T>
+class binding
+{
+private:
+
+ struct impl : public detail::impl_base
{
T value_;
std::function<T ()> expression_;
}
};
+ template<typename> friend class binding;
+
std::shared_ptr<impl> impl_;
public:
binding()
return impl_->bound();
}
- void depend_on(const binding<T>& other)
+ template<typename T2>
+ void depend_on(const binding<T2>& other)
{
impl_->depend_on(other.impl_);
}
binding<T> operator+(T other) const
{
- auto self = impl_;
-
- return binding<T>(
- [other, self] { return other + self->get(); },
- *this);
+ return transformed([other](T self) { return self + other; });
}
binding<T> operator+(const binding<T>& other) const
binding<T> operator-() const
{
- auto self = impl_;
-
- return binding<T>(
- [self] { return -self->get(); },
- *this);
+ return transformed([](T self) { return -self; });
}
binding<T> operator-(const binding<T>& other) const
binding<T> operator*(T other) const
{
- auto self = impl_;
-
- return binding<T>(
- [other, self] { return other * self->get(); },
- *this);
+ return transformed([other](T self) { return self * other; });
}
binding<T> operator*(const binding<T>& other) const
binding<T> operator/(T other) const
{
- auto self = impl_;
-
- return binding<T>(
- [other, self] { return self->get() / other; },
- *this);
+ return transformed([other](T self) { return self / other; });
}
binding<T> operator/(const binding<T>& other) const
binding<bool> operator==(T other) const
{
- auto self = impl_;
-
- return binding<bool>(
- [other, self] { return self->get() == other; },
- *this);
+ return transformed([other](T self) { return self == other; });
}
binding<bool> operator==(const binding<T>& other) const
binding<bool> operator!=(T other) const
{
- auto self = impl_;
-
- return binding<bool>(
- [other, self] { return self->get() != other; },
- *this);
+ return transformed([other](T self) { return self != other; });
}
binding<bool> operator!=(const binding<T>& other) const
other);
}
+ template<typename T2>
+ binding<T2> as() const
+ {
+ return transformed([](T val) { return static_cast<T2>(val); });
+ }
+
+ template<typename Func>
+ auto transformed(const Func& func) const -> binding<decltype(func(impl_->value_))>
+ {
+ typedef decltype(func(impl_->value_)) R;
+ auto self = impl_;
+
+ return binding<R>(
+ [self, func] { return func(self->get()); },
+ *this);
+ }
+
void unbind()
{
impl_->unbind();
struct scene_producer::impl
{
constraints pixel_constraints_;
- std::vector<layer> layers_;
+ std::list<layer> layers_;
interaction_aggregator aggregator_;
+ binding<int64_t> frame_number_;
impl(int width, int height)
: pixel_constraints_(width, height)
layer& create_layer(
const spl::shared_ptr<frame_producer>& producer, int x, int y)
{
- layer layer(producer);
+ layer& layer = create_layer(producer);
layer.position.x.set(x);
layer.position.y.set(y);
+ return layer;
+ }
+
+ layer& create_layer(const spl::shared_ptr<frame_producer>& producer)
+ {
+ layer layer(producer);
+
layers_.push_back(layer);
return layers_.back();
}
+ binding<int64_t> frame()
+ {
+ return frame_number_;
+ }
+
frame_transform get_transform(const layer& layer) const
{
frame_transform transform;
frames.push_back(frame);
}
+ frame_number_.set(frame_number_.get() + 1);
+
return draw_frame(frames);
}
return impl_->create_layer(producer, x, y);
}
+layer& scene_producer::create_layer(
+ const spl::shared_ptr<frame_producer>& producer)
+{
+ return impl_->create_layer(producer);
+}
+
+binding<int64_t> scene_producer::frame()
+{
+ return impl_->frame();
+}
+
draw_frame scene_producer::receive_impl()
{
return impl_->render_frame();
if (params.size() < 1 || params.at(0) != L"[SCENE]")
return core::frame_producer::empty();
- auto scene = spl::make_shared<scene_producer>(160, 90);
+ auto scene = spl::make_shared<scene_producer>(1280, 720);
- std::vector<std::wstring> sub_params;
- binding<int> text_width(10);
- binding<int> padding(1);
- binding<int> panel_width = padding + text_width + padding;
+ binding<double> text_width(10);
+ binding<double> padding(1);
+ binding<double> panel_width = padding + text_width + padding;
+ binding<double> panel_height(50);
auto subscription = panel_width.on_change([&]
{
padding.set(2);
text_width.set(20);
+ auto create_param = [](std::wstring elem) -> std::vector<std::wstring>
+ {
+ std::vector<std::wstring> result;
+ result.push_back(elem);
+ return result;
+ };
+
+ scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"car")));
+ std::vector<std::wstring> sub_params;
sub_params.push_back(L"[FREEHAND]");
- sub_params.push_back(L"100");
- sub_params.push_back(L"50");
+ sub_params.push_back(L"640");
+ sub_params.push_back(L"360");
scene->create_layer(create_producer(frame_factory, format_desc, sub_params), 10, 10);
sub_params.clear();
- sub_params.push_back(L"BLUE");
- scene->create_layer(create_producer(frame_factory, format_desc, sub_params), 110, 10);
- sub_params.clear();
-
- sub_params.push_back(L"SP");
- scene->create_layer(create_producer(frame_factory, format_desc, sub_params), 50, 50);
- sub_params.clear();
+ scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"BLUE")), 110, 10);
+
+ //scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"SP")), 50, 50);
+
+ auto& upper_left = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/upper_left")));
+ auto& upper_right = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/upper_right")));
+ auto& lower_left = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/lower_left")));
+ auto& lower_right = scene->create_layer(create_producer(frame_factory, format_desc, create_param(L"scene/lower_right")));
+
+ binding<double> panel_x = scene->frame()
+ .as<double>()
+ .transformed([](double v) { return std::sin(v / 20.0); })
+ * 20.0
+ + 40.0;
+ binding<double> panel_y(500);
+ upper_left.position.x = panel_x;
+ upper_left.position.y = panel_y;
+ upper_right.position.x = upper_left.position.x + upper_left.producer.get()->pixel_constraints().width + panel_width;
+ upper_right.position.y = upper_left.position.y;
+ lower_left.position.x = upper_left.position.x;
+ lower_left.position.y = upper_left.position.y + upper_left.producer.get()->pixel_constraints().height + panel_height;
+ lower_right.position.x = upper_right.position.x;
+ lower_right.position.y = lower_left.position.y;
+
+ text_width.set(500);
+ panel_height.set(50);
return scene;
}