On Sun, 16 May 2010 14:31:30 -0400, Sam Wilson <tecywiz...@hotmail.com> wrote:

> Hello knowledgeable clutter people,
> 
> I created an actor to handle drawing sprite based animations, and I am
> wondering if it is the correct way to do it.
> 
> The code is written in Vala, but it won't compile with the stock clutter
> bindings since I am using cogl_texture_new_from_sub_texture  which isn't
> bound.  There's a patch attached to fix it.

The actor looks pretty neat to me. I just have a couple of points that
might make it slightly better.

- There's no need to override the pick method if the actor has no
  children and you are just drawing the color to fill the actor's
  allocation. The default implementation in ClutterActor will do this
  for you.

- You might want to make a separate material for each frame that is
  private to the actor and use that to render the texture rather than
  using Cogl.set_source_texture. This will help Cogl optimize the
  rendering better because Cogl.set_source_texture effectively ends up
  editing a global convenience material which would cause a flush of
  Cogl's journal. You should also use this material to implement the
  opacity of the actor. So _frames would become an array of
  Cogl.Materials and your init function would be something like this
  (although I don't really know Vala so I'm just guessing the syntax):

  _frames[i] = new Cogl.Material ();
  _frames[i].set_layer(0, new Texture.from_sub_texture (...));

  and then your paint method would be like this:

  guint8 paint_opacity = get_paint_opacity ();
  _frames[i].set_color4ub (paint_opacity,
                           paint_opacity,
                           paint_opacity,
                           paint_opacity);
  Cogl.set_source (frames[i]);
  ...

- It's currently much more efficient to use Cogl.rectangle rather than
  the path API to draw the texture. Cogl isn't clever enough to
  recognise that the path you've created is a simple rectangle and it
  ends up having to fill the stencil buffer to render the texture into
  the path. Using Cogl.rectangle instead means it can just directly
  submit a quad to OpenGL.

- You might want to implement the setter for the 'frame' property so
  that it queues a redraw. Otherwise it would probably be difficult to
  use ClutterActor.animate to animate the property. I don't know what's
  the right way to do that in Vala.

Hope that helps.

- Neil

> Here's my actor:
> 
> using Cogl;
> 
> public class SpriteActor : Clutter.Actor
> {
>   private Texture _tex;
>   private Texture[] _frames;
>   
>   public int frame_width { get; construct set; }
>   public int frame_height { get; construct set; }
>   public int n_frames { get; construct set; }
>   
>   public int frame { get; set; }
>   
>   private SpriteActor()
>   {
>     Object();
>   }
>   
>   public SpriteActor.from_file(int width, int height,
>                                int frames, string path)
>                                 throws GLib.Error
>   {
>     Object(frame_width: width, frame_height: height, n_frames: frames);
>     
>     _tex = new Texture.from_file(path,
>                                  TextureFlags.NO_SLICING,
>                                  PixelFormat.ANY);
>     
>     init();
>   }
>   
>   public SpriteActor.from_bitmap(int width, int height,
>                                  int frames, Bitmap bit)
>   {
>     Object(frame_width: width, frame_height: height, n_frames: frames);
>     
>     _tex = new Texture.from_bitmap(bit,
>                                    TextureFlags.NO_SLICING,
>                                    PixelFormat.ANY);
>     
>     init();
>   }
>   
>   private void init()
>   {
>     //this.notify["frame"].connect(() => {queue_redraw();});
>   
>     _frames = new Texture[n_frames];
>     
>     for (int i = 0; i < n_frames; i++)
>     {
>       _frames[i] = new Texture.from_sub_texture(_tex, i * frame_width,
>                                                 0, frame_width,
>                                                 frame_height);
>     }
>   }
>   
>   protected override void paint()
>   {  
>     Cogl.set_source_texture(_frames[frame]);
>     Cogl.path_rectangle(0, 0, width, height);
>     Cogl.path_fill();
>   }
>   
>   protected override void pick(Clutter.Color c)
>   {
>     Cogl.set_source_color4ub(c.red, c.green, c.blue, c.alpha);
>     Cogl.path_rectangle(0, 0, width, height);
>     Cogl.path_fill();
>   }
> }
> 
> 
> diff --git a/vapi/cogl-1.0.vapi b/vapi/cogl-1.0.vapi
> index 9f356d3..9c2c807 100644
> --- a/vapi/cogl-1.0.vapi
> +++ b/vapi/cogl-1.0.vapi
> @@ -152,6 +152,7 @@ namespace Cogl {
>               public Texture.from_bitmap (Cogl.Bitmap bmp_handle, 
> Cogl.TextureFlags flags, Cogl.PixelFormat internal_format);
>               public Texture.from_data (uint width, uint height, 
> Cogl.TextureFlags flags, Cogl.PixelFormat format, Cogl.PixelFormat 
> internal_format, uint rowstride, [CCode (array_length = false)] uchar[] data);
>               public Texture.from_file (string filename, Cogl.TextureFlags 
> flags, Cogl.PixelFormat internal_format) throws GLib.Error;
> +             public Texture.from_sub_texture(Cogl.Texture full_texture, int 
> sub_x, int sub_y, int sub_width, int sub_height);
>               public int get_data (Cogl.PixelFormat format, uint rowstride, 
> uchar[] data);
>               public Cogl.PixelFormat get_format ();
>               public uint get_height ();
Attachment: smime.p7s (application/x-pkcs7-signature)
-- 
To unsubscribe send a mail to clutter+unsubscr...@o-hand.com

Reply via email to