Stroboscope Layer

This time I will try to add new type of layer to Synfig which produces stroboscope effect. Stroboscope means reducing frame rate by given ratio. As you might expect, I don’t know how to add a new layer type. Yet.

First I’ve started to search git history for the changes related to layer type which functionality is most close to my idea — Time Loop. Searching for «Time Loop» string I found that its files are

synfig-core/trunk/src/modules/lyr_std/timeloop.cpp
synfig-core/trunk/src/modules/lyr_std/timeloop.h

I’ve decided to use those files as a template for my new Stroboscope layer. I just copied them to

synfig-core/trunk/src/modules/lyr_std/stroboscope.cpp
synfig-core/trunk/src/modules/lyr_std/stroboscope.h

The “Stroboscope” effect is much simpler than “TimeLoop”. That’s how I’ve modified source code of timeloop layer:

--- timeloop.cpp	2009-12-07 18:40:11.000000000 +0600
+++ stroboscope.cpp	2009-12-07 18:47:53.000000000 +0600
@@ -1,12 +1,13 @@
 /* === S Y N F I G ========================================================= */
-/*!	\file timeloop.cpp
-**	\brief Implementation of the "Time Loop" layer
+/*!	\file stroboscope.cpp
+**	\brief Implementation of the "Stroboscope" layer
 **
 **	$Id$
 **
 **	\legal
 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
 **	Copyright (c) 2007, 2008 Chris Moore
+**	Copyright (c) 2009 Ray Frederikson
 **
 **	This package is free software; you can redistribute it and/or
 **	modify it under the terms of the GNU General Public License as
@@ -32,7 +33,7 @@
 #	include <config.h>
 #endif

-#include "timeloop.h"
+#include "stroboscope.h"
 #include <synfig/valuenode.h>
 #include <synfig/valuenode_const.h>
 #include <synfig/valuenode_subtract.h>
@@ -52,59 +53,38 @@

 /* === G L O B A L S ======================================================= */

-SYNFIG_LAYER_INIT(Layer_TimeLoop);
-SYNFIG_LAYER_SET_NAME(Layer_TimeLoop,"timeloop");
-SYNFIG_LAYER_SET_LOCAL_NAME(Layer_TimeLoop,N_("Time Loop"));
-SYNFIG_LAYER_SET_CATEGORY(Layer_TimeLoop,N_("Other"));
-SYNFIG_LAYER_SET_VERSION(Layer_TimeLoop,"0.2");
-SYNFIG_LAYER_SET_CVS_ID(Layer_TimeLoop,"$Id$");
+SYNFIG_LAYER_INIT(Layer_Stroboscope);
+SYNFIG_LAYER_SET_NAME(Layer_Stroboscope,"stroboscope");
+SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Stroboscope,N_("Stroboscope"));
+SYNFIG_LAYER_SET_CATEGORY(Layer_Stroboscope,N_("Other"));
+SYNFIG_LAYER_SET_VERSION(Layer_Stroboscope,"0.1");
+SYNFIG_LAYER_SET_CVS_ID(Layer_Stroboscope,"$Id$");

 /* === P R O C E D U R E S ================================================= */

 /* === M E T H O D S ======================================================= */

-Layer_TimeLoop::Layer_TimeLoop()
+Layer_Stroboscope::Layer_Stroboscope()
 {
-	old_version=false;
-	only_for_positive_duration=false;
-	symmetrical=true;
-	link_time=0;
-	local_time=0;
-	duration=1;
+	ratio=1;
 }

-Layer_TimeLoop::~Layer_TimeLoop()
+Layer_Stroboscope::~Layer_Stroboscope()
 {
 }

 bool
-Layer_TimeLoop::set_param(const String & param, const ValueBase &value)
+Layer_Stroboscope::set_param(const String & param, const ValueBase &value)
 {
-	if(old_version)
-	{
-		IMPORT(start_time);
-		IMPORT(end_time);
-	}
-	else
-	{
-		IMPORT(local_time);
-		IMPORT(link_time);
-		IMPORT(duration);
-		IMPORT(only_for_positive_duration);
-		IMPORT(symmetrical);
-	}
+	IMPORT(ratio);

 	return Layer::set_param(param,value);
 }

 ValueBase
-Layer_TimeLoop::get_param(const String & param)const
+Layer_Stroboscope::get_param(const String & param)const
 {
-	EXPORT(link_time);
-	EXPORT(local_time);
-	EXPORT(duration);
-	EXPORT(only_for_positive_duration);
-	EXPORT(symmetrical);
+	EXPORT(ratio);
 	EXPORT_NAME();
 	EXPORT_VERSION();

@@ -112,141 +92,36 @@
 }

 Layer::Vocab
-Layer_TimeLoop::get_param_vocab()const
+Layer_Stroboscope::get_param_vocab()const
 {
 	Layer::Vocab ret(Layer::get_param_vocab());

-	ret.push_back(ParamDesc("link_time")
-		.set_local_name(_("Link Time"))
-	);
-
-	ret.push_back(ParamDesc("local_time")
-		.set_local_name(_("Local Time"))
-	);
-
-	ret.push_back(ParamDesc("duration")
-		.set_local_name(_("Duration"))
-	);
-
-	ret.push_back(ParamDesc("only_for_positive_duration")
-		.set_local_name(_("Only For Positive Duration"))
-	);
-
-	ret.push_back(ParamDesc("symmetrical")
-		.set_local_name(_("Symmetrical"))
+	ret.push_back(ParamDesc("ratio")
+		.set_local_name(_("Ratio"))
 	);

 	return ret;
 }

-bool
-Layer_TimeLoop::set_version(const String &ver)
-{
-	if (ver=="0.1")
-		old_version = true;
-
-	return true;
-}
-
-void
-Layer_TimeLoop::reset_version()
-{
-	// if we're not converting from an old version of the layer, there's nothing to do
-	if (!old_version)
-		return;
-
-	old_version = false;
-
-	// these are the conversions to go from 0.1 to 0.2:
-	//
-	//	 local_time = start_time
-	//	 duration = end_time - start_time
-	//	 if (time < start_time)
-	//	   link_time = -duration : if we want to reproduce the old behaviour - do we?
-	//	 else
-	//		 link_time = 0
-
-	// convert the static parameters
-	local_time = start_time;
-	duration = end_time - start_time;
-	only_for_positive_duration = true;
-	symmetrical = false;
-
-	//! \todo layer version 0.1 acted differently before start_time was reached - possibly due to a bug
-	link_time = 0;
-
-	// convert the dynamic parameters
-	const DynamicParamList &dpl = dynamic_param_list();
-
-	// if neither start_time nor end_time are dynamic, there's nothing more to do
-	if (dpl.count("start_time") == 0 && dpl.count("end_time") == 0)
-		return;
-
-	etl::rhandle<ValueNode> start_time_value_node, end_time_value_node;
-	LinkableValueNode* duration_value_node;
-
-	if (dpl.count("start_time"))
-	{
-		start_time_value_node = dpl.find("start_time")->second;
-		disconnect_dynamic_param("start_time");
-	}
-	else
-		start_time_value_node = ValueNode_Const::create(start_time);
-
-	if (dpl.count("end_time"))
-	{
-		end_time_value_node = dpl.find("end_time")->second;
-		disconnect_dynamic_param("end_time");
-	}
-	else
-		end_time_value_node = ValueNode_Const::create(end_time);
-
-	duration_value_node = ValueNode_Subtract::create(Time(0));
-	duration_value_node->set_link("lhs", end_time_value_node);
-	duration_value_node->set_link("rhs", start_time_value_node);
-
-	connect_dynamic_param("local_time", start_time_value_node);
-	connect_dynamic_param("duration",   duration_value_node);
-}
-
 void
-Layer_TimeLoop::set_time(Context context, Time t)const
+Layer_Stroboscope::set_time(Context context, Time t)const
 {
 	Time time = t;

-	if (!only_for_positive_duration || duration > 0)
-	{
-		if (duration == 0)
-			t = link_time;
-		else if (duration > 0)
-		{
-			t -= local_time;
-			t -= floor(t / duration) * duration;
-			t  = link_time + t;
-		}
-		else
-		{
-			t -= local_time;
-			t -= floor(t / -duration) * -duration;
-			t  = link_time - t;
-		}
-
-		// for compatibility with v0.1 layers; before local_time is reached, take a step back
-		if (!symmetrical && time < local_time)
-			t -= duration;
-	}
+	if (ratio != 0)
+		t = floor(t/ratio)*ratio;

 	context.set_time(t);
 }

 Color
-Layer_TimeLoop::get_color(Context context, const Point &pos)const
+Layer_Stroboscope::get_color(Context context, const Point &pos)const
 {
 	return context.get_color(pos);
 }

 bool
-Layer_TimeLoop::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
+Layer_Stroboscope::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
 {
 	return context.accelerated_render(surface,quality,renddesc,cb);
 }
--- timeloop.h	2009-12-07 18:40:11.000000000 +0600
+++ stroboscope.h	2009-12-07 18:47:53.000000000 +0600
@@ -1,12 +1,13 @@
 /* === S Y N F I G ========================================================= */
-/*!	\file timeloop.h
-**	\brief Header file for implementation of the "Time Loop" layer
+/*!	\file stroboscope.h
+**	\brief Header file for implementation of the "Stroboscope" layer
 **
 **	$Id$
 **
 **	\legal
 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
 **	Copyright (c) 2008 Chris Moore
+**	Copyright (c) 2009 Ray Frederikson
 **
 **	This package is free software; you can redistribute it and/or
 **	modify it under the terms of the GNU General Public License as
@@ -23,8 +24,8 @@

 /* === S T A R T =========================================================== */

-#ifndef __SYNFIG_TIMELOOP_H
-#define __SYNFIG_TIMELOOP_H
+#ifndef __SYNFIG_STROBOSCOPE_H
+#define __SYNFIG_STROBOSCOPE_H

 /* === H E A D E R S ======================================================= */

@@ -39,34 +40,24 @@

 /* === C L A S S E S & S T R U C T S ======================================= */

-class Layer_TimeLoop : public synfig::Layer
+class Layer_Stroboscope : public synfig::Layer
 {
 	SYNFIG_LAYER_MODULE_EXT

 private:
-	synfig::Time	link_time;
-	synfig::Time	local_time;
-	synfig::Time	duration;
-
-	synfig::Time	start_time;
-	synfig::Time	end_time;
-	bool			old_version;
-	bool			only_for_positive_duration;
-	bool			symmetrical; // the 0.1 version of this layer behaved differently before 'start_time' was reached
+	synfig::Time	ratio;

 protected:
-	Layer_TimeLoop();
+	Layer_Stroboscope();

 public:
-	~Layer_TimeLoop();
+	~Layer_Stroboscope();

 	virtual bool set_param(const synfig::String & param, const synfig::ValueBase &value);

 	virtual synfig::ValueBase get_param(const synfig::String & param)const;

 	virtual Vocab get_param_vocab()const;
-	virtual bool set_version(const synfig::String &ver);
-	virtual void reset_version();
 	virtual synfig::Color get_color(synfig::Context context, const synfig::Point &pos)const;

 	virtual void set_time(synfig::Context context, synfig::Time time)const;

Next I need to know how to register new type of layer. To do that I need to examine history again and to find entries for some recently added layer. Hmmm… Which layer was added recently? Don’t know. Let’s look into NEWS file for recently released 0.62.00 version. Aha, synfig-studio/NEWS file says that there is a “New layer Curve Warp”.

Little search for word “Curve” gives me commit 5ae346e017651b10ea2b2b6e1391db5d4bc4243f:

First stab at adding genete’s suggested ‘Curve Warp’ layer. It’s pretty slow at the moment, because it uses get_color() to render the context pixel by pixel rather than using accelerated_render() to render a block at once.

There’s another interesting commit – 7357ac6302a24809752101271b0879771dc4348d.

Now we can figure how to add a new layer. Let’s look at the changes I did:

-------------------------- synfig-core/po/POTFILES.in --------------------------
index ad8b051..531a369 100644
@@ -33,6 +33,8 @@ src/modules/lyr_std/sphere_distort.cpp
src/modules/lyr_std/sphere_distort.h
src/modules/lyr_std/stretch.cpp
src/modules/lyr_std/stretch.h
+src/modules/lyr_std/stroboscope.cpp
+src/modules/lyr_std/stroboscope.h
src/modules/lyr_std/supersample.cpp
src/modules/lyr_std/supersample.h
src/modules/lyr_std/timeloop.cpp

----------------- synfig-core/src/modules/lyr_std/Makefile.am -----------------
index 786d76d..8dc51b1 100644
@@ -51,7 +51,9 @@ liblyr_std_la_SOURCES = \
sphere_distort.h \
sphere_distort.cpp \
curvewarp.cpp \
-	curvewarp.h
+	curvewarp.h \
+	stroboscope.cpp \
+	stroboscope.h

liblyr_std_la_CXXFLAGS = \
@SYNFIG_CFLAGS@

------------------- synfig-core/src/modules/lyr_std/main.cpp -------------------
index faa0d7a..27c7000 100644
@@ -67,6 +67,7 @@
#include "warp.h"
#include "timeloop.h"
#include "curvewarp.h"
+#include "stroboscope.h"

#endif

@@ -98,6 +99,7 @@ MODULE_INVENTORY_BEGIN(liblyr_std)
LAYER(Layer_Shade)
LAYER(Layer_Bevel)
LAYER(Layer_TimeLoop)
+		LAYER(Layer_Stroboscope)
LAYER(Layer_SphereDistort)
LAYER(CurveWarp)
END_LAYERS

After that I compiled and tested new layer. It’s generally works, but there is one problem. It stops to work inside of encapsulated canvas. I’m stuck and don’t know how to solve it yet.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: