Difference between revisions of "Dev:Adding a Layer"

From Synfig Studio :: Documentation
Jump to: navigation, search
m (work in progress)
 
m
Line 211: Line 211:
 
  #include <synfig/layer.h>
 
  #include <synfig/layer.h>
  
Define the class which implements our layer.  We inherit from the Layer class.
+
=== The Class ===
 +
 
 +
Define the class which implements our layer.  We inherit from the Layer class.  For this simple example we only define five methods.  The rest will be inherited from the Layer class.
 
   
 
   
 
  /* === C L A S S E S & S T R U C T S ======================================= */
 
  /* === C L A S S E S & S T R U C T S ======================================= */
Line 217: Line 219:
 
  class Desaturate : public synfig::Layer
 
  class Desaturate : public synfig::Layer
 
  {
 
  {
 +
 +
This is standard.  Just use it for every layer.  It declares members to hold the layer's name, version, category, etc., and also declares a method to create() the layer.  See synfig/src/synfig/layer.h for its definition.
 +
 
     SYNFIG_LAYER_MODULE_EXT
 
     SYNFIG_LAYER_MODULE_EXT
 +
 +
=== The Methods ===
 +
 +
Then we declare the five methods we're going to implement.  First "get_param()".  Since our layer isn't going to have any parameters, all it needs to do is make the layer's name and
 +
version available.
 +
 
  public:
 
  public:
 
     virtual synfig::ValueBase get_param(const synfig::String&)const;
 
     virtual synfig::ValueBase get_param(const synfig::String&)const;
 +
 +
This one returns a list of the layer's parameters.  We have no parameters, so we return an empty list.
 +
 
     virtual Vocab get_param_vocab()const;
 
     virtual Vocab get_param_vocab()const;
 +
 +
This one is used to find the color of a single given pixel.  It's used by the "Info" panel to display the R,G,B values as you mouse over the canvas.  It's also used if our layer has any transformation layers over the top of it.  The absence of a working implementation of this method in the "Text" layer is why distorting text currently causes render artifacts.
 +
 
     virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const;
 
     virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const;
 +
 +
This one is used to render a large rectangular piece of our layer in one go.  It typically calls the accelerated_render() method for the layers under our layer (the 'context') and then modifies the results of that call in some way:
 +
 
     virtual bool accelerated_render(synfig::Context,synfig::Surface*,int,
 
     virtual bool accelerated_render(synfig::Context,synfig::Surface*,int,
 
                                     const synfig::RendDesc &, synfig::ProgressCallback *)const;
 
                                     const synfig::RendDesc &, synfig::ProgressCallback *)const;
 +
 +
This one returns true always, meaning that this layer's output depends on the layers under it (the 'context'):
 +
 
     virtual bool reads_context()const { return true; }
 
     virtual bool reads_context()const { return true; }
 
  }; // END of class Desaturate
 
  }; // END of class Desaturate
 
   
 
   
 
  #endif
 
  #endif

Revision as of 17:42, 16 April 2008

Here's an example of how to add a simple layer to an existing module. For this example I picked something very easy: a layer which removes all colour from the layers beneath it. I will call this creation "Desaturate", and add it to the mod_filter module.

The Code

So first I need to create desaturate.h and desaturate.cpp in the synfig/src/modules/mod_filter/ folder:

desaturate.h:

/* === S Y N F I G ========================================================= */
/*! \file desaturate.h
**  \brief Header file for implementation of the "Desaturate" layer
**
**  \legal
**  Copyright (c) 2008 Chris Moore
**
**  This package is free software; you can redistribute it and/or
**  modify it under the terms of the GNU General Public License as
**  published by the Free Software Foundation; either version 2 of
**  the License, or (at your option) any later version.
**
**  This package is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  General Public License for more details.
**  \endlegal
** ========================================================================= */

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

#ifndef __SYNFIG_DESATURATE_H
#define __SYNFIG_DESATURATE_H

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

#include <synfig/layer.h>

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

class Desaturate : public synfig::Layer
{
    SYNFIG_LAYER_MODULE_EXT
public:
    virtual synfig::ValueBase get_param(const synfig::String&)const;
    virtual Vocab get_param_vocab()const;
    virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const;
    virtual bool accelerated_render(synfig::Context,synfig::Surface*,int,
                                    const synfig::RendDesc &, synfig::ProgressCallback *)const;
    virtual bool reads_context()const { return true; }
}; // END of class Desaturate

#endif

desaturate.cpp:

/* === S Y N F I G ========================================================= */
/*! \file desaturate.cpp
**  \brief Implementation of the "Desaturate" layer
**
**  \legal
**  Copyright (c) 2008 Chris Moore
**
**  This package is free software; you can redistribute it and/or
**  modify it under the terms of the GNU General Public License as
**  published by the Free Software Foundation; either version 2 of
**  the License, or (at your option) any later version.
**
**  This package is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  General Public License for more details.
**  \endlegal
** ========================================================================= */

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

#ifdef USING_PCH
#   include "pch.h"
#else
#ifdef HAVE_CONFIG_H
#   include <config.h>
#endif

#include "desaturate.h"

#include <synfig/context.h>
#include <synfig/paramdesc.h>
#include <synfig/renddesc.h>
#include <synfig/surface.h>
#include <synfig/value.h>

#endif

using namespace synfig;

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

SYNFIG_LAYER_INIT(Desaturate);
SYNFIG_LAYER_SET_NAME(Desaturate,"desaturate");
SYNFIG_LAYER_SET_LOCAL_NAME(Desaturate,N_("Desaturate"));
SYNFIG_LAYER_SET_CATEGORY(Desaturate,N_("Filters"));
SYNFIG_LAYER_SET_VERSION(Desaturate,"0.1");
SYNFIG_LAYER_SET_CVS_ID(Desaturate,"$Id$");

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

ValueBase
Desaturate::get_param(const String &param)const
{
    EXPORT_NAME();
    EXPORT_VERSION();

    return ValueBase();
}

Layer::Vocab
Desaturate::get_param_vocab()const
{
    return Layer::Vocab();
}

Color
Desaturate::get_color(Context context, const Point &getpos)const
{
    Color tmp(context.get_color(getpos));
    return tmp.set_s(0);
}

bool
Desaturate::accelerated_render(Context              context,
                               Surface*             surface,
                               int                  quality,
                               const RendDesc&      renddesc,
                               ProgressCallback*    cb
                              )const
{
    SuperCallback supercb(cb,0,9500,10000);

    // render the context onto the given surface
    if(!context.accelerated_render(surface,quality,renddesc,&supercb))
        return false;

    // set the saturation of each pixel to zero
    int x,y;
    Surface::pen pen(surface->begin());
    for(y=0;y<renddesc.get_h();y++,pen.inc_y(),pen.dec_x(x))
        for(x=0;x<renddesc.get_w();x++,pen.inc_x())
        {
            Color tmp(pen.get_value());
            pen.put_value(tmp.set_s(0));
        }

    // mark our progress as finished
    if(cb && !cb->amount_complete(10000,10000)) return false;
    return true;
}

Then I need to edit modules/mod_filter/Makefile.am and add these two files to the list of source files (maintain alphabetical order please):

libmod_filter_la_SOURCES = blur.cpp blur.h colorcorrect.cpp colorcorrect.h desaturate.cpp desaturate.h halftone2.cpp halftone2.h lumakey.cpp lumakey.h radialblur.cpp radialblur.h main.cpp halftone.cpp halftone.h halftone3.cpp halftone3.h

And finally we edit modules/mod_filter/main.cpp. Add this with the other #include lines:

#include "desaturate.h"

and add this with the other LAYER(...) lines:

LAYER(Desaturate)

then rebuild (including the autoreconf, ./configure, etc., to get the new files added to the Makefile) and we're done.

The Description

I'll break the header up into sections, describing each part:

The initial comment

This contains basic documentation and legal stuff. Just copy, paste, and edit from another file.

/* === S Y N F I G ========================================================= */
/*! \file desaturate.h
**  \brief Header file for implementation of the "Desaturate" layer
**
**  \legal
**  Copyright (c) 2008 Chris Moore
**
**  This package is free software; you can redistribute it and/or
**  modify it under the terms of the GNU General Public License as
**  published by the Free Software Foundation; either version 2 of
**  the License, or (at your option) any later version.
**
**  This package is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  General Public License for more details.
**  \endlegal
** ========================================================================= */

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

Protection against Multiple Inclusion

This #ifndef is a standard way to make sure the header is only compiled once, even if it happens to be included multiple times. Use a unique symbol, based on the file name.

#ifndef __SYNFIG_DESATURATE_H
#define __SYNFIG_DESATURATE_H

Include files which are needed. We're not doing anything much, so all we need to include is layer.h, which defines the Layer class that all layers inherit from.

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

#include <synfig/layer.h>

The Class

Define the class which implements our layer. We inherit from the Layer class. For this simple example we only define five methods. The rest will be inherited from the Layer class.

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

class Desaturate : public synfig::Layer
{

This is standard. Just use it for every layer. It declares members to hold the layer's name, version, category, etc., and also declares a method to create() the layer. See synfig/src/synfig/layer.h for its definition.

    SYNFIG_LAYER_MODULE_EXT

The Methods

Then we declare the five methods we're going to implement. First "get_param()". Since our layer isn't going to have any parameters, all it needs to do is make the layer's name and version available.

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

This one returns a list of the layer's parameters. We have no parameters, so we return an empty list.

    virtual Vocab get_param_vocab()const;

This one is used to find the color of a single given pixel. It's used by the "Info" panel to display the R,G,B values as you mouse over the canvas. It's also used if our layer has any transformation layers over the top of it. The absence of a working implementation of this method in the "Text" layer is why distorting text currently causes render artifacts.

    virtual synfig::Color get_color(synfig::Context, const synfig::Point&)const;

This one is used to render a large rectangular piece of our layer in one go. It typically calls the accelerated_render() method for the layers under our layer (the 'context') and then modifies the results of that call in some way:

    virtual bool accelerated_render(synfig::Context,synfig::Surface*,int,
                                    const synfig::RendDesc &, synfig::ProgressCallback *)const;

This one returns true always, meaning that this layer's output depends on the layers under it (the 'context'):

    virtual bool reads_context()const { return true; }
}; // END of class Desaturate

#endif